package com.knecon.fforesight.service.layoutparser.server;

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

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.knecon.fforesight.service.layoutparser.internal.api.data.taas.ResearchDocumentData;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingType;
import com.knecon.fforesight.service.layoutparser.processor.LayoutParsingPipeline;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.Document;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.textblock.TextBlock;
import com.knecon.fforesight.service.layoutparser.processor.python_api.model.image.ImageServiceResponse;
import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableServiceResponse;
import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.VisualLayoutParsingResponse;
import com.knecon.fforesight.service.layoutparser.processor.services.factory.DocumentGraphFactory;
import com.knecon.fforesight.service.layoutparser.processor.services.mapper.TaasDocumentDataMapper;
import com.knecon.fforesight.service.layoutparser.processor.utils.DrawingOptions;
import com.knecon.fforesight.service.layoutparser.server.utils.AbstractTest;
import com.knecon.fforesight.service.layoutparser.server.utils.visualizations.PdfDraw;

import lombok.SneakyThrows;

public class BdrJsonBuildTest extends AbstractTest {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private LayoutParsingPipeline layoutParsingPipeline;


    @SneakyThrows
    protected Document buildGraph(File file) {

        return DocumentGraphFactory.buildDocumentGraph(LayoutParsingType.CLARIFYND,
                layoutParsingPipeline.parseLayout(LayoutParsingType.CLARIFYND,
                        file,
                        new ImageServiceResponse(),
                        new TableServiceResponse(),
                        new VisualLayoutParsingResponse(),
                        Map.of("file",file.toString())));
    }


    @Test
    @SneakyThrows
    public void testBDRFile199865() {

        File file = new ClassPathResource("files/bdr/Drucksache_19_9865.pdf").getFile();
        Document document = buildGraph(file);
        ResearchDocumentData researchDocumentData = TaasDocumentDataMapper.fromDocument(document);
        assertThat(researchDocumentData).isNotNull();

    }


    @Test
    @Disabled
    public void writeBDRDocumentData() throws IOException {

        String sourcePath = "/tmp/bdr_files";
        String targetPath = "/tmp/result";
        Paths.get(targetPath).toFile().mkdirs();

        List<File> files = Files.walk(Paths.get(sourcePath)).filter(currentPath -> currentPath.toString().endsWith(".pdf")).map(Path::toFile).toList();

        System.out.printf("Found %d files \n", files.size());
        for (int i = 0; i < files.size(); i++) {
            System.out.println(i + ": " + files.get(i));
        }

        System.out.println();

        for (var file : files) {
            long start = System.currentTimeMillis();
            System.out.println("Starting Structure Analysis for: " + file);
            Document document = buildGraph(file);

            long start2 = System.currentTimeMillis();
            ResearchDocumentData researchDocumentData = TaasDocumentDataMapper.fromDocument(document);
            researchDocumentData.setOriginalFile(file.toString());
            System.out.printf(", mapped to research data %d ms \n", System.currentTimeMillis() - start2);

            File jsonFile = Paths.get(targetPath, file.getName().replace(".pdf", ".json")).toFile();
            try (FileOutputStream fileOutputStream = new FileOutputStream(jsonFile)) {
                System.out.println("json written to: " + jsonFile);
                fileOutputStream.write(objectMapper.writeValueAsBytes(researchDocumentData));
            }
            File visualizationFile = Paths.get(targetPath, file.getName().replace(".pdf", "_BBOX.pdf")).toFile();
            visualizeSemanticNodes(file, visualizationFile, document, document.getTextBlock());
            System.out.println("visualization pdf written to: " + visualizationFile);
            System.out.printf("Full analysis and file creation took %s\n\n", Duration.ofMillis(System.currentTimeMillis() - start));
        }

    }


    private static void visualizeSemanticNodes(File file, File resultingFileName, Document document, TextBlock textBlock) throws IOException {

        try (PDDocument pdDocument = Loader.loadPDF(file); var outputStream = new FileOutputStream(resultingFileName)) {
            PdfDraw.drawDocumentGraph(pdDocument, document);
            PdfDraw.drawTextBlock(pdDocument, textBlock, DrawingOptions.builder().stroke(true).strokeWidth(0.1f).strokeColor(Color.YELLOW).build());
            pdDocument.save(outputStream);
        }
    }

}
