package click.kamil.springstatemachineexporter.html.exporter;

import click.kamil.springstatemachineexporter.analysis.model.AnalysisResult;
import click.kamil.springstatemachineexporter.exporter.ExportOptions;
import click.kamil.springstatemachineexporter.exporter.PlantUml;
import click.kamil.springstatemachineexporter.exporter.StateMachineExporter;
import click.kamil.springstatemachineexporter.model.Transition;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.SourceStringReader;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class HtmlExporter implements StateMachineExporter {

    private final PlantUml pumlExporter = new PlantUml();
    private final SvgDecorator svgDecorator = new SvgDecorator();
    private final ObjectMapper objectMapper = new ObjectMapper()
            .enable(SerializationFeature.INDENT_OUTPUT);

    @Override
    public String export(AnalysisResult result, ExportOptions options) {
        try {
            // 1. Generate PUML with identifiers embedded
            ExportOptions enrichedOptions = ExportOptions.builder()
                    .useLambdaGuards(options.isUseLambdaGuards())
                    .renderChoicesAsDiamonds(options.isRenderChoicesAsDiamonds())
                    .embedIdentifiers(true) // Force identifying classes in SVG
                    .build();

            String puml = pumlExporter.export(result, enrichedOptions);

            // 2. Generate SVG from PUML
            SourceStringReader reader = new SourceStringReader(puml);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            reader.generateImage(os, new FileFormatOption(FileFormat.SVG));
            String rawSvg = os.toString(StandardCharsets.UTF_8);

            // 3. Decorate SVG (Clean responsive, styles, etc.)
            String decoratedSvg = svgDecorator.decorate(rawSvg);

            // 4. Load Template
            String template = loadTemplate();

            // 5. Prepare Metadata JSON
            String metadataJson = objectMapper.writeValueAsString(result);

            // 6. Inject Data
            return template
                    .replace("{{MACHINE_NAME}}", result.getName())
                    .replace("{{SVG_CONTENT}}", decoratedSvg)
                    .replace("{{METADATA_JSON}}", metadataJson);

        } catch (Exception e) {
            log.error("Failed to export to HTML", e);
            throw new RuntimeException("HTML export failed", e);
        }
    }

    private String loadTemplate() {
        try (InputStream is = getClass().getResourceAsStream("/html/template.html")) {
            if (is == null) throw new RuntimeException("HTML template not found");
            return new BufferedReader(new InputStreamReader(is))
                    .lines()
                    .collect(Collectors.joining("\n"));
        } catch (Exception e) {
            throw new RuntimeException("Failed to load HTML template", e);
        }
    }

    @Override
    public String export(String name, List<Transition> transitions, Set<String> startStates, Set<String> endStates, ExportOptions options) {
        AnalysisResult mockResult = AnalysisResult.builder()
                .name(name)
                .states(click.kamil.springstatemachineexporter.ast.app.TransitionStateUtils.findAllStates(transitions, startStates, endStates))
                .transitions(transitions)
                .startStates(startStates)
                .endStates(endStates)
                .build();
        return export(mockResult, options);
    }

    @Override
    public String getFileExtension() {
        return ".html";
    }
}
