package com.chinaweal.aiccs.schedule;

import com.chinaweal.aiccs.aiccs.abnormal.entity.CaseZfReport;
import com.chinaweal.aiccs.aiccs.abnormal.entity.TSWrit;
import com.chinaweal.aiccs.aiccs.abnormal.service.CaseZfReportService;
import com.chinaweal.aiccs.aiccs.abnormal.service.TSWritService;
import com.chinaweal.aiccs.common.util.CaseNoGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 执法数据推送定时任务
 *
 * @author lwd
 * @since 2025-10-29
 */
@Slf4j
@Configuration
@Component
public class LawEnforcementDataPushScheduled {

    @Resource
    private CaseZfReportService caseZfReportService;

    @Resource
    private CaseNoGenerator caseNoGenerator;

    @Autowired
    private TSWritService tsWritService;

    /**
     * 定时生成推送执法数据
     * 案件编号规则：22位编码（9位市场监督管理局代码 + 1位分类码 + 8位登记日期 + 4位流水号）
     * 分类码：1-行政处罚案件，2-行政复议案件，3-行政诉讼案件，4-行政赔偿案件
     * 流水号范围：5001-9999，如果当天用完则向前查找有空余流水号的日期
     */
    @Scheduled(cron = "${scheduling.cron.lawEnforcementDataPush}")
    public void lawEnforcementDataPush() {
        try {
            log.info("开始执行执法数据推送定时任务");

            // 从视图查询需要处理的数据
            List<CaseZfReport> caseZfReportList = caseZfReportService.querycasereportview();
            log.info("从视图查询到 {} 条执法数据", caseZfReportList.size());

            if (caseZfReportList == null || caseZfReportList.isEmpty()) {
                log.info("没有需要处理的执法数据");
                return;
            }

            // 获取数据库中已存在的所有案件编号
            Set<String> existingCaseNos = getAllExistingCaseNos();

            // 按办案日期和业务序列号分组处理
            Map<String, List<CaseZfReport>> groupedReports = groupReportsByCaseFidateAndBizseq(caseZfReportList);

            int successCount = 0;
            int failCount = 0;

            // 处理每个分组
            for (Map.Entry<String, List<CaseZfReport>> entry : groupedReports.entrySet()) {
                List<CaseZfReport> groupReports = entry.getValue();

                // 按业务序列号排序
                groupReports.sort((r1, r2) -> {
                    String bizSeq1 = r1.getBizseq() != null ? r1.getBizseq() : "";
                    String bizSeq2 = r2.getBizseq() != null ? r2.getBizseq() : "";
                    return bizSeq1.compareTo(bizSeq2);
                });

                // 为每个案件生成唯一编号并保存
                for (CaseZfReport report : groupReports) {
                    try {
                        // 生成新的案件编号
                        String newCaseNo = caseNoGenerator.generateUniqueCaseNo(report, existingCaseNos);

                        // 设置新的案件编号
                        report.setCaseno(newCaseNo);

                        List<TSWrit> tsWritList = tsWritService.lambdaQuery()
                                .eq(TSWrit::getBizseq, report.getBizseq())
                                .eq(TSWrit::getPripid, report.getPripid())
                                .eq(TSWrit::getWritstype,"33")
                                .list();

                        if (tsWritList.size() > 0) {
                            report.setXtpath(tsWritList.get(0).getPath());
                        }

                        // 查询数据库中是否已存在相同 BIZSEQ 和 PRIPID 的数据（修正原查询条件：第二个 eq 应为 report.getPripid()）
                        List<CaseZfReport> existingReports = caseZfReportService.lambdaQuery()
                                .eq(CaseZfReport::getBizseq, report.getBizseq())
                                .eq(CaseZfReport::getPripid, report.getPripid()) // 原错误：report.getBizseq() 改为 report.getPripid()
                                .list();

                        // 关键修改：仅当数据库中无对应数据时，才执行保存操作
                        if (existingReports == null || existingReports.isEmpty()) {
                            // 保存到数据库
                            boolean success = caseZfReportService.saveCaseZfReport(report, null);

                            if (success) {
                                successCount++;
                                existingCaseNos.add(newCaseNo); // 添加到已存在集合，避免重复
                                log.debug("成功保存执法数据，案件编号: {}, 原业务序列号: {}",
                                        newCaseNo, report.getBizseq());
                            } else {
                                failCount++;
                                log.warn("保存执法数据失败，案件编号: {}, 原业务序列号: {}",
                                        newCaseNo, report.getBizseq());
                            }
                        } else {
                            log.info("数据库中已存在该业务数据，无需重复保存，业务序列号: {}, 主体标识: {}",
                                    report.getBizseq(), report.getPripid());
                        }
                    } catch (Exception e) {
                        failCount++;
                        log.error("处理执法数据失败，业务序列号: {}, 错误: {}",
                                report.getBizseq(), e.getMessage(), e);
                    }
                }
            }

            log.info("执法数据推送处理完成，成功: {}, 失败: {}", successCount, failCount);

        } catch (Exception e) {
            log.error("执法数据推送定时任务执行失败", e);
        }
    }

    /**
     * 按办案日期和业务序列号分组
     */
    private Map<String, List<CaseZfReport>> groupReportsByCaseFidateAndBizseq(List<CaseZfReport> reportList) {
        Map<String, List<CaseZfReport>> groupedMap = new TreeMap<>(); // 使用TreeMap按日期排序

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        for (CaseZfReport report : reportList) {
            String groupKey;

            if (report.getCasefidate() != null) {
                groupKey = sdf.format(report.getCasefidate());
            } else {
                groupKey = sdf.format(new Date());
            }

            groupedMap.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(report);
        }

        return groupedMap;
    }

    /**
     * 更新现有记录的所有字段
     */
    private void updateExistingReport(CaseZfReport existingReport, CaseZfReport newReport) {
        existingReport.setCasesou(newReport.getCasesou());
        existingReport.setCasecon(newReport.getCasecon());
        existingReport.setCluetime(newReport.getCluetime());
        existingReport.setCasearea(newReport.getCasearea());
        existingReport.setCasename(newReport.getCasename());
        existingReport.setCasereason(newReport.getCasereason());
        existingReport.setCasefiauthname(newReport.getCasefiauthname());
        existingReport.setCasefidate(newReport.getCasefidate());
        existingReport.setCasedepname(newReport.getCasedepname());
        existingReport.setPenresult(newReport.getPenresult());
        existingReport.setCaseendtype(newReport.getCaseendtype());
        existingReport.setCaseenddate(newReport.getCaseenddate());
        existingReport.setPartytype(newReport.getPartytype());
        existingReport.setUnitname(newReport.getUnitname());
        existingReport.setLerep(newReport.getLerep());
        existingReport.setDom(newReport.getDom());
        existingReport.setTel(newReport.getTel());
        existingReport.setCertype(newReport.getCertype());
        existingReport.setCerno(newReport.getCerno());
        existingReport.setIllegfact(newReport.getIllegfact());
        existingReport.setPendecissdate(newReport.getPendecissdate());
        existingReport.setIllegacttypename(newReport.getIllegacttypename());
        existingReport.setPenbasis(newReport.getPenbasis());
        existingReport.setDiscretionfact(newReport.getDiscretionfact());
        existingReport.setDiscretionapp(newReport.getDiscretionapp());
        existingReport.setPencontent(newReport.getPencontent());
        existingReport.setPentypename(newReport.getPentypename());
        existingReport.setCaseval(newReport.getCaseval());
        existingReport.setPenam(newReport.getPenam());
        existingReport.setRefamoord(newReport.getRefamoord());
        existingReport.setForfam(newReport.getForfam());
        existingReport.setForgoods(newReport.getForgoods());
        existingReport.setPenauthname(newReport.getPenauthname());
        existingReport.setPendecno(newReport.getPendecno());
        existingReport.setExetype(newReport.getExetype());
        existingReport.setPublish(newReport.getPublish());
    }

    /**
     * 获取数据库中已存在的所有案件编号
     */
    private Set<String> getAllExistingCaseNos() {
        Set<String> existingCaseNos = new HashSet<>();

        try {
            // 先查询总记录数，避免无限循环
            int totalCount = caseZfReportService.list().size();
            if (totalCount <= 0) {
                log.info("没有查询到现有案件编号");
                return existingCaseNos;
            }

            // 分批查询，避免内存溢出
            int pageSize = 1000;
            int totalPages = (totalCount + pageSize - 1) / pageSize; // 计算总页数
            int currentPage = 0;

            while (currentPage < totalPages) {
                int offset = currentPage * pageSize;
                Map<String, Object> queryParams = new HashMap<>();
                queryParams.put("offset", offset);
                queryParams.put("pageSize", pageSize);

                List<CaseZfReport> batch = caseZfReportService.queryCaseListByCondition(queryParams);

                if (batch == null || batch.isEmpty()) {
                    log.warn("第 {} 页查询结果为空，提前结束分页查询", currentPage);
                    break;
                }

                for (CaseZfReport report : batch) {
                    if (report.getCaseno() != null) {
                        existingCaseNos.add(report.getCaseno());
                    }
                }

                currentPage++;
            }

            log.info("已加载 {} 个现有案件编号到缓存（总记录数：{}）", existingCaseNos.size(), totalCount);

        } catch (Exception e) {
            log.error("获取现有案件编号失败", e);
            // 返回空集合，允许继续执行
        }

        return existingCaseNos;
    }
}
