package click.kamil.springstatemachineexporter.analysis.service;

import click.kamil.springstatemachineexporter.analysis.enricher.SemanticCallChainDedup;
import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.analysis.model.EntryPoint;
import click.kamil.springstatemachineexporter.analysis.model.LinkResolution;
import click.kamil.springstatemachineexporter.analysis.model.MatchedTransition;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class EnrichmentServiceSemanticMergeTest {

    @Test
    void refreshMergeShouldUseSemanticDedupNotEntryPointOnly() {
        EntryPoint entryPoint = EntryPoint.builder()
                .name("POST /api/order/pay")
                .className("com.example.Api")
                .methodName("pay")
                .build();
        TriggerPoint trigger = TriggerPoint.builder()
                .event("PAY")
                .build();
        List<MatchedTransition> matched = List.of(MatchedTransition.builder()
                .event("PAY")
                .sourceState("NEW")
                .targetState("PAID")
                .build());

        CallChain existing = CallChain.builder()
                .entryPoint(entryPoint)
                .triggerPoint(trigger)
                .linkResolution(LinkResolution.RESOLVED)
                .matchedTransitions(matched)
                .methodChain(List.of("a", "b", "c"))
                .build();
        CallChain refreshed = CallChain.builder()
                .entryPoint(entryPoint)
                .triggerPoint(trigger)
                .linkResolution(LinkResolution.RESOLVED)
                .matchedTransitions(matched)
                .methodChain(List.of("a"))
                .build();

        List<CallChain> merged = SemanticCallChainDedup.mergeRefresh(
                List.of(existing),
                List.of(refreshed),
                SemanticCallChainDedup.KeepStrategy.SHORTEST);

        assertThat(merged).hasSize(1);
        assertThat(merged.get(0).getMethodChain()).containsExactly("a");

        Transition payT = new Transition();
        payT.setSourceStates(List.of(State.of("NEW", "NEW")));
        payT.setTargetStates(List.of(State.of("PAID", "PAID")));
        payT.setEvent(Event.of("PAY", "PAY"));

        AnalysisResult result = AnalysisResult.builder()
                .name("OrderStateMachineConfig")
                .transitions(List.of(payT))
                .metadata(CodebaseMetadata.builder().callChains(merged).build())
                .build();

        new EnrichmentService(List.of()).relinkAfterPropertyResolution(result, null, null);

        assertThat(result.getMetadata().getCallChains()).hasSize(1);
        assertThat(result.getMetadata().getCallChains().get(0).getMethodChain()).containsExactly("a");
        assertThat(result.getMetadata().getCallChains().get(0).getMatchedTransitions()).hasSize(1);
    }
}
