package com.yunyan.business.service.impl;

import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.yunyan.business.constant.BusinessCacheConstants;
import com.yunyan.business.constant.TemplateEpType;
import com.yunyan.business.document.templateEpStrategy.AnnotationTplStrategyFactory;
import com.yunyan.business.document.templateEpStrategy.TplStrategy;
import com.yunyan.business.domain.FinalData;
import com.yunyan.business.mapper.FinalDataMapper;
import com.yunyan.business.pojo.admin.dto.FinalDataListDto;
import com.yunyan.business.pojo.admin.dto.FinalImportExcelDto;
import com.yunyan.business.service.IBudgetImportService;
import com.yunyan.business.service.IFinalDataService;
import com.yunyan.business.service.IFinalImport2023Service;
import com.yunyan.business.service.ISyncService;
import com.yunyan.business.utils.CrawlWebDateUtils;
import com.yunyan.common.config.YunYanConfig;
import com.yunyan.common.constant.Constants;
import com.yunyan.common.core.redis.RedisCache;
import com.yunyan.common.utils.StringUtils;
import com.yunyan.common.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class SyncServiceImpl implements ISyncService {

    @Autowired
    private FinalDataMapper finalDataMapper;

    @Autowired
    private IFinalDataService finalDataService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IBudgetImportService budgetImportService;

    @Autowired
    private IFinalImport2023Service iFinalImport2023Service;

    @Async
    @Override
    public Future<String> PDFComparator(Long id, String remotePDFUrl, String localPdfUrl, String publicSite) {

        FinalData finalData = finalDataMapper.selectById(id);
        if(Objects.isNull(finalData)){
            throw new RuntimeException("决算数据不存在");
        }
        // 获取远程文件url
        //String remotePDFUrl = finalData.getPublicSite()+finalData.getPublicDownloadUrl();
        // 本机地址的文件路径
        String localPath = YunYanConfig.getProfile();
        String localFilePath = localPath + StringUtils.substringAfter(localPdfUrl, Constants.RESOURCE_PREFIX);

        //比较信息 todo 是否保存 比较信息
        StringBuilder msg = new StringBuilder();

        Integer publicSiteAccess = 0;
        Integer publicDownloadUrlAccess = 0;
        Integer publicConsistent = 0;

        //判断 公开网址的PDF是否不为空
        if(StringUtils.isNotBlank(remotePDFUrl)) {
            //文件读取器
            PdfReader remotePdfReader = null;
            PdfReader localPdfReader = null;
            try {
                //重试机制
                int maxTry = 3;
                int tryi = 0;
                URL remoteFileUrl = null;
                while (tryi++ < maxTry) {
                    try {
                        // 远程文件URL
                        remoteFileUrl = new URL(remotePDFUrl);
                        // 加载远程PDF文件
                        remotePdfReader = new PdfReader(remoteFileUrl);
                        if(null != remotePdfReader) {
                            break;
                        }
                    } catch (IOException e) {
                        msg.setLength(0);
                        msg.append("读取远程的pdf文件异常 ");
                        log.error("读取远程的pdf文件异常, [{}], [{}]", e.getMessage(), e);
                    }
                    if(null == remotePdfReader) {
                        Thread.sleep(1000);
                    }
                }


                //远程PDF文件的状态
                if(null != remoteFileUrl) {
                    publicDownloadUrlAccess = 1;
                }

                try {
                    // 加载本地PDF文件
                    localPdfReader = new PdfReader(localFilePath);
                } catch (IOException e) {
                    msg.append("读取本地的pdf文件异常 ");
                    log.error("读取本地的pdf文件异常, [{}], [{}]", e.getMessage(), e);
                }

                if(null != remotePdfReader && null != localPdfReader) {
                    // 比较远程和本地文件的页数
                    int remotePages = remotePdfReader.getNumberOfPages();
                    int localPages = localPdfReader.getNumberOfPages();
                    if (remotePages != localPages) {
                        msg.append("远程文件和本地文件页数不一致 ");
                        log.error("远程文件和本地文件页数不一致");
                        //throw new RuntimeException("远程文件和本地文件页数不一致");
                    }
                    // 比较远程和本地文件每页的内容
                    for (int i = 1; i <= remotePages; i++) {

                        String remotePageContent = PdfTextExtractor.getTextFromPage(remotePdfReader, i);
                        remotePageContent = remotePageContent.replaceAll("\\s+|\\.+", "");

                        String localPageContent = PdfTextExtractor.getTextFromPage(localPdfReader, i);
                        localPageContent = localPageContent.replaceAll("\\s+|\\.+", "");

                        if (!remotePageContent.equals(localPageContent)) {
                            msg.append("第 " + i + " 页内容不一致 ");
                            log.error("第 " + i + " 页内容不一致");
                        }
                    }
                }
            } catch (IOException e ) {
                msg.append("比较pdf文件异常 ");
                log.error("比较pdf文件异常, [{}], [{}]", e.getMessage(), e);
            } catch (Exception e) {
                msg.append("比较pdf文件异常 ");
                log.error("比较pdf文件异常, [{}], [{}]", e.getMessage(), e);
            } finally {
                // 关闭读取器
                if(null != remotePdfReader) {
                    remotePdfReader.close();
                }
                if(null != localPdfReader) {
                    localPdfReader.close();
                }
            }
        }

        //检测网址的正常性
        Boolean publicUrlFlag =  HttpUtils.checkUrlConnection(finalData.getPublicSite());
        if(publicUrlFlag) {
            publicSiteAccess = 1;
        }

        //获取日期
        String createDateStr = CrawlWebDateUtils.getDate(publicSite);

        //获取标题 判断= 2024年度部门预算, 预算或者决算
        Integer publicStatus = 0;
        if(finalData.getType() == 2 ) {
            String articleTitleH1 = CrawlWebDateUtils.getArticleTitleH1(publicSite);
            String articleTitleCompare1 = DateUtil.thisYear() + "年";
            String articleTitleCompare2 = "部门预算";
            if(StringUtils.isNotBlank(articleTitleH1) && articleTitleH1.contains(articleTitleCompare1) && articleTitleH1.contains(articleTitleCompare2)) {
                publicStatus = 1;
            }
        }

        //如果是决算的, 又变了 div class="newsView bgwhite"  div.newsTitle
        if(finalData.getType() == 1) {
            publicStatus = 1;

            //2024年 决算
            /*String articleTitleH1 = CrawlWebDateUtils.getArticleTitle2023FinalNewsTitle(publicSite);
            String articleTitleCompare1 = (DateUtil.thisYear() - 1)  + "年";
            String articleTitleCompare2 = "部门决算";
            if(StringUtils.isNotBlank(articleTitleH1) && articleTitleH1.contains(articleTitleCompare1) && articleTitleH1.contains(articleTitleCompare2)) {
                publicStatus = 1;
            }*/
        }


        FinalData updateEntity = new FinalData();
        updateEntity.setId(id);
        updateEntity.setPublicSiteAccess(publicSiteAccess);
        updateEntity.setPublicDownloadUrlAccess(publicDownloadUrlAccess);
        updateEntity.setPublicStatus(publicStatus);

        if(StringUtils.isNotBlank(createDateStr)) {
            //"yyyy-MM-dd hh:mm"
            Date publicTime = DateUtil.parse(createDateStr);
            updateEntity.setPublicTime(publicTime);
        }

        if(msg.length() == 0) {
            updateEntity.setPublicConsistent(1);
        } else {
            updateEntity.setPublicConsistent(0);
        }
        finalDataService.updateById(updateEntity);

        if(msg.length() == 0) {
            return new AsyncResult<>("远程文件和本地文件内容一致");
        }

        return new AsyncResult<>("远程文件和本地文件内容不一致");
    }

    @Override
    public Future<String> checkWebsiteFillStatue(Long id, String publicSite) {
        FinalData finalData = finalDataMapper.selectById(id);
        if(Objects.isNull(finalData)){
            throw new RuntimeException("决算数据不存在");
        }

        Integer publicSiteAccess = 0;
        Integer publicDownloadUrlAccess = 0;
        Integer publicConsistent = 0;

        //检测网址的正常性
        Boolean publicUrlFlag =  HttpUtils.checkUrlConnection(finalData.getPublicSite());
        if(publicUrlFlag) {
            publicSiteAccess = 1;
        }
        //检测下载网址的正常性
        Boolean publicDownloadUrlAccessFlag =  HttpUtils.checkUrlConnection(finalData.getPublicDownloadUrl());
        if(publicDownloadUrlAccessFlag) {
            publicDownloadUrlAccess = 1;
        }


        //获取日期
        String createDateStr = CrawlWebDateUtils.getDate(publicSite);

        //获取标题 判断= 2024年度部门预算, 预算或者决算
        Integer publicStatus = 0;
        if(finalData.getType() == 2 ) {
            String articleTitleH1 = CrawlWebDateUtils.getArticleTitleH1(publicSite);
            String articleTitleCompare1 = DateUtil.thisYear() + "年";
            String articleTitleCompare2 = "部门预算";
            if(StringUtils.isNotBlank(articleTitleH1) && articleTitleH1.contains(articleTitleCompare1) && articleTitleH1.contains(articleTitleCompare2)) {
                publicStatus = 1;
            }
        }
        //如果是决算的, 又变了 div class="newsView bgwhite"  div.newsTitle
        if(finalData.getType() == 1) {
            publicStatus = 1;

            //2024年 决算
            String articleTitleH1 = "";
            if(!TemplateEpType.Y2023FT2BS.getCode().equals(finalData.getTemplateExportType())) {
                //不是 百色市时
                articleTitleH1 = CrawlWebDateUtils.getArticleTitleH1(publicSite);
            } else {
                //2023 百色时
                articleTitleH1 = CrawlWebDateUtils.getArticleTitle2023BaiseFinalNewsTitle(publicSite);
            }
            String articleTitleCompare1 = (DateUtil.thisYear() - 1)  + "年";
            String articleTitleCompare2 = "部门决算";
            if(StringUtils.isNotBlank(articleTitleH1) && articleTitleH1.contains(articleTitleCompare1) && articleTitleH1.contains(articleTitleCompare2)) {
                publicStatus = 1;
            }
        }


        FinalData updateEntity = new FinalData();
        updateEntity.setId(id);
        updateEntity.setPublicSiteAccess(publicSiteAccess);
        updateEntity.setPublicDownloadUrlAccess(publicDownloadUrlAccess);
        updateEntity.setPublicStatus(publicStatus);

        if(StringUtils.isNotBlank(createDateStr)) {
            //"yyyy-MM-dd hh:mm"
            Date publicTime = DateUtil.parse(createDateStr);
            updateEntity.setPublicTime(publicTime);
        }

        finalDataService.updateById(updateEntity);

        return new AsyncResult<>("检测公开网址结束");
    }

    @Async
    @Override
    public Future<String> generateDocument(Long id) {

        //判断 redis 是否存在
        String generateDocumentKey = BusinessCacheConstants.GENERATE_DOCUMENT_FINAL_FLAG + id;
        if (redisCache.hasKey(generateDocumentKey)) {
            log.error("文档在生成中, 请稍后再试~");
            return new AsyncResult<>("文档在生成中, 请稍后再试~");
        }

        redisCache.setCacheObject(generateDocumentKey, 1, 40, TimeUnit.SECONDS);

        FinalData finalData = finalDataMapper.selectById(id);
        if(Objects.isNull(finalData)){
            throw new RuntimeException("决算数据不存在");
        }

        try {
            TplStrategy tplStrategy = AnnotationTplStrategyFactory.getTemplateStrategy(finalData.getTemplateExportType());
            tplStrategy.exportSave(finalDataService, id);
        } catch (Exception e) {
            log.error("生成文档异常");
            return new AsyncResult<>("生成文档异常， 请稍后再试, 或者联系管理员~");
        } finally {
            if (redisCache.hasKey(generateDocumentKey)) {
                redisCache.deleteObject(generateDocumentKey);
            }
        }

        //去掉 redis redis 是否存在

        return new AsyncResult<>("生成文档成功");
    }

    @Async
    @Override
    public Future<String> finalImportExcel(FinalImportExcelDto dto) {
        switchYear(dto);
        return new AsyncResult<>("正在导入决算的文档");
    }

    @Async
    @Override
    public Future<String> budgetImportExcel(FinalImportExcelDto dto) {
        budgetImportService.budgetImportExcel(dto);

        return new AsyncResult<>("正在导入预算的文档");
    }

    @Async
    @Override
    public Future<String> checkWebsiteFillStatue(FinalDataListDto dto) {
        finalDataService.checkWebsiteFillStatue(dto);
        return new AsyncResult<>("正在检测公开网址状态");
    }

    /**
     * 按照年份, 使用对应的读取
     * @param dto
     */
    private void switchYear(FinalImportExcelDto dto) {
        switch (dto.getYear()) {
            case "2022":
                finalDataService.finalImportExcel(dto);
                break;
            case "2023":
                iFinalImport2023Service.finalImportExcel(dto);
                break;
            case "2024":
                iFinalImport2023Service.finalImportExcel(dto);
                break;
            case "2025":
                iFinalImport2023Service.finalImportExcel(dto);
                break;
            default:
                iFinalImport2023Service.finalImportExcel(dto);
                break;
        }

    }
}
