package click.kamil.springstatemachineexporter.exporter;

import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.analysis.model.BusinessFlow;
import click.kamil.springstatemachineexporter.analysis.model.FlowStep;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.model.Event;
import click.kamil.springstatemachineexporter.model.State;
import click.kamil.springstatemachineexporter.model.Transition;
import click.kamil.springstatemachineexporter.service.JsonImportService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;

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

class JsonInterchangeContractTest {

    @Test
    void shouldExportCompleteSelfContainedAnalysisResult(@TempDir Path tempDir) throws Exception {
        Transition transition = new Transition();
        transition.setEvent(Event.of("OrderEvent.PAY", "com.example.order.OrderEvent.PAY"));
        transition.setSourceStates(List.of(State.of("OrderState.NEW", "com.example.order.OrderState.NEW")));
        transition.setTargetStates(List.of(State.of("OrderState.PAID", "com.example.order.OrderState.PAID")));

        AnalysisResult original = AnalysisResult.builder()
                .name("com.example.config.OrderStateMachineConfiguration")
                .stateTypeFqn("com.example.order.OrderState")
                .eventTypeFqn("com.example.order.OrderEvent")
                .states(Set.of(State.of("OrderState.NEW", "com.example.order.OrderState.NEW")))
                .transitions(List.of(transition))
                .startStates(Set.of("com.example.order.OrderState.NEW"))
                .endStates(Set.of("com.example.order.OrderState.PAID"))
                .renderChoicesAsDiamonds(true)
                .flows(List.of(BusinessFlow.builder().name("Pay flow").steps(List.of(FlowStep.ofEvent("PAY"))).build()))
                .metadata(CodebaseMetadata.empty())
                .build();

        Path jsonFile = tempDir.resolve("machine.json");
        Files.writeString(jsonFile, new JsonExporter().export(original, ExportOptions.builder().build()));

        AnalysisResult imported = new JsonImportService().importAnalysisResult(jsonFile);

        assertThat(imported.getName()).isEqualTo(original.getName());
        assertThat(imported.getStateTypeFqn()).isEqualTo("com.example.order.OrderState");
        assertThat(imported.getEventTypeFqn()).isEqualTo("com.example.order.OrderEvent");
        assertThat(imported.getStates()).hasSize(1);
        assertThat(imported.getFlows()).extracting(BusinessFlow::getName).containsExactly("Pay flow");
        assertThat(imported.isRenderChoicesAsDiamonds()).isTrue();
        assertThat(imported.getTransitions().get(0).getEvent().fullIdentifier())
                .isEqualTo("com.example.order.OrderEvent.PAY");
    }
}
