package com.qingyun.service.compare.strategy;

import com.github.difflib.patch.DeltaType;
import com.qingyun.common.exception.ServiceException;
import com.qingyun.common.utils.StringUtils;
import com.qingyun.service.compare.BoundingBox;
import com.qingyun.service.compare.DiffRegion;
import com.qingyun.service.compare.PdfDiffWithPosition;
import com.qingyun.service.domain.ContractCompareResult;
import com.qingyun.service.domain.ContractCompareTask;
import com.qingyun.service.mapper.ContractCompareResultMapper;
import com.qingyun.service.mapper.ContractCompareTaskMapper;
import com.qingyun.service.utils.PdfUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.Objects;


@Component
@Order(1)
public class PdfComparisonStrategy extends AbstractFileComparisonStrategy  implements Ordered {

    @Autowired
    private PdfUtil pdfUtil;

    @Autowired
    private PdfDiffWithPosition pdfDiffWithPosition;

    @Autowired
    private ContractCompareResultMapper compareResultMapper;

    @Autowired
    private ContractCompareTaskMapper contractCompareTaskMapper;

    @Override
    protected void doExtract(ContractCompareTask task) {
        if (!task.getFirstContractUrl().endsWith(".pdf")) {
            task.setFirstContractName(task.getFirstContractName() + ".pdf");
        }
        if (!task.getSecondContractUrl().endsWith(".pdf")) {
            task.setSecondContractName(task.getSecondContractName() + ".pdf");
        }

        File firstFile = null;
        File secondFile = null;
        try {
            firstFile = pdfUtil.downloadFile(task.getFirstContractUrl(), task.getFirstContractName());
            PDDocument firstDocument = Loader.loadPDF(firstFile);
            if (firstDocument == null) {
                throw new ServiceException("解析PDF文件失败");
            }
//            // 判断是否是扫描件pdf
//            if (PdfScanChecker.isScannedPdf(firstDocument)) {
//                // 扫描件pdf -> orc识别 -> 重组成新的文字pdf
//
//            }
            task.setFirstPageNum(firstDocument.getNumberOfPages());
            if (firstDocument.getNumberOfPages() > 0) {
                task.setFirstContractContent(firstDocument.getPage(0).getContents().toString());
                task.setFirstWidth(firstDocument.getPage(0).getMediaBox().getWidth());
                task.setFirstHeight(firstDocument.getPage(0).getMediaBox().getHeight());
            }
            secondFile = pdfUtil.downloadFile(task.getSecondContractUrl(), task.getSecondContractName());
            PDDocument secondDocument = Loader.loadPDF(secondFile);
            if (secondDocument == null) {
                throw new ServiceException("解析PDF文件失败");
            }
            task.setSecondPageNum(secondDocument.getNumberOfPages());
            if (secondDocument.getNumberOfPages() > 0) {
                task.setSecondWidth(secondDocument.getPage(0).getMediaBox().getWidth());
                task.setSecondHeight(secondDocument.getPage(0).getMediaBox().getHeight());
            }
            firstDocument.close();
            secondDocument.close();

        } catch (Exception e) {
            log.error("解析PDF文件失败", e);
            updateTaskStatus(task, 4, "解析PDF文件失败");
            return;
        }
        updateTaskStatus(task, 2, "文本提取完成");
    }

    @Override
    protected List<DiffRegion> doCompare(ContractCompareTask task) {
        return pdfDiffWithPosition.compare(task);
    }

    @Override
    protected ContractCompareResult buildResult(ContractCompareTask task, DiffRegion change) {
        ContractCompareResult contractCompareResult = new ContractCompareResult();
        contractCompareResult.setTaskId(task.getTaskId());

        contractCompareResult.setBaseDiffContent(StringUtils.isNotBlank(change.getSourceText()) ? change.getSourceText() : "");
        contractCompareResult.setCompareDiffContent(StringUtils.isNotBlank(change.getTargetText()) ? change.getTargetText() : "");

        // 源文本的变动类型，要根据目标的变动类型来处理，change - change , delete - insert, insert - delete
        if (Objects.equals(change.getChangeType(), DeltaType.CHANGE.name())) {
            contractCompareResult.setBaseDiffType("change");
            contractCompareResult.setCompareDiffType("change");
        } else if (Objects.equals(change.getChangeType(), DeltaType.DELETE.name())) {
            contractCompareResult.setBaseDiffType("insert");
            contractCompareResult.setCompareDiffType("delete");
        } else if (Objects.equals(change.getChangeType(), DeltaType.INSERT.name())) {
            contractCompareResult.setBaseDiffType("delete");
            contractCompareResult.setCompareDiffType("insert");
        }

        if (change.getSourceBox() != null) {
            BoundingBox sourceBox = change.getSourceBox();
            contractCompareResult.setBaseBoxArea(
                sourceBox.getX() + "," + sourceBox.getY() + "," + sourceBox.getWidth() + "," + sourceBox.getHeight());

            contractCompareResult.setBasePageNum(change.getSourcePage());
        } else {
            // 没有源文本，则取目标文本的定位
            BoundingBox targetBox = change.getTargetBox();
            contractCompareResult.setBaseBoxArea(
                targetBox.getX() + "," + targetBox.getY() + "," + targetBox.getWidth() + "," + targetBox.getHeight());
            contractCompareResult.setBasePageNum(change.getTargetPage());
        }
        if (change.getTargetBox() != null) {
            BoundingBox targetBox = change.getTargetBox();
            contractCompareResult.setCompareBoxArea(
                targetBox.getX() + "," + targetBox.getY() + "," + targetBox.getWidth() + "," + targetBox.getHeight());
            contractCompareResult.setComparePageNum(change.getTargetPage());
        } else {
            // 没有目标文本，则取源文本的定位
            BoundingBox sourceBox = change.getSourceBox();
            contractCompareResult.setCompareBoxArea(
                sourceBox.getX() + "," + sourceBox.getY() + "," + sourceBox.getWidth() + "," + sourceBox.getHeight());
            contractCompareResult.setComparePageNum(change.getSourcePage());
        }
        contractCompareResult.setCreateTime(new Date());
        return contractCompareResult;
    }

    @Override
    protected void saveResults(List<ContractCompareResult> results) {
        compareResultMapper.insertBatch(results);
    }

    @Override
    protected void updateTaskStatus(ContractCompareTask task, int status, String msg) {
        task.setStatus(status);
        task.setErrorMsg(msg);
        contractCompareTaskMapper.updateById(task);
    }

    @Override
    public boolean supports(String fileExtension) {
        return "pdf".equals(fileExtension);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
