package com.chinaweal.aiccs.schedule;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chinaweal.aiccs.aicbizqy.entity.datamove.*;
import com.chinaweal.aiccs.aicbizqy.mapper.datamove.*;
import com.chinaweal.aiccs.aiccs.system.entity.TRBaseCode;
import com.chinaweal.aiccs.aiccs.system.service.TRBaseCodeService;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 注销主体自动移出定时任务
 * <p>
 * 功能：每天凌晨读取当天注销的市场主体，
 * 自动移出其未移出的经营异常名录、严重违法记录，
 * 并为行政处罚记录插入信用修复信息。
 *
 * @author ZhouXiYao
 * @since 2026-03-31
 */
@Slf4j
@Component
public class CancelEntRemoveSchedule {

    @Autowired
    private EBaseInfoDataMoveMapper eBaseInfoMapper;

    @Autowired
    private AoOpaDetailDataMoveMapper aoOpaDetailMapper;

    @Autowired
    private ELiIlldisdetailDataMoveMapper eliIlldisdetailMapper;

    @Autowired
    private EImCaseDataMoveMapper eImCaseMapper;

    @Autowired
    private CaseCreInformationDataMoveMapper caseCreInformationMapper;

    @Autowired
    private TRBaseCodeService trBaseCodeService;

    @Autowired
    private RedisService redisService;

    /**
     * LOCK_KEY
     */
    private static final String REDIS_LOCK = "CANCEL_ENT_LOCK";
    /**
     * 默认移出机关代码
     */
    private static final String DEFAULT_REMOVE_ORG = "150000";
    /**
     * 默认移出机关名称
     */
    private static final String DEFAULT_REMOVE_ORG_CN = "内蒙古市场监督管理局";

    /**
     * 每天凌晨2点执行注销主体自动移出任务
     */
    @Scheduled(cron = "${scheduling.cron.cancelEntRemove:-}")
    @Transactional(rollbackFor = Exception.class)
    public void executeCancelEntRemove() {
        if (redisService.exists(REDIS_LOCK)) {
            log.info("其他节点已在执行注销主体自动移出任务，本次任务自动跳过");
            return;
        }
        log.info("==========开始执行注销主体自动移出任务==========");
        long startTime = System.currentTimeMillis();
        redisService.set(REDIS_LOCK, StringUtils.EMPTY, 3600);
        try {
            // 获取当天日期
            LocalDate today = LocalDate.now().minusDays(1);
            String todayStr = today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            log.info("查询日期: {}", todayStr);

            // 1. 查询当天注销的市场主体
            List<EBaseInfo> cancelledEntList = queryCancelledEntities(today);
            log.info("查询到{}条当天注销的市场主体", cancelledEntList.size());

            if (cancelledEntList.isEmpty()) {
                log.info("没有需要处理的注销主体，任务结束");
                return;
            }

            // 2. 统计处理结果
            int abnRemoveCount = 0;
            int illegalRemoveCount = 0;
            int penaltyRepairCount = 0;

            // 3. 遍历处理每个注销主体
            for (EBaseInfo ent : cancelledEntList) {
                log.info("开始处理注销主体: PRIPID={}, ENTNAME={}, UNISCID={}",
                        ent.getPripid(), ent.getEntname(), ent.getUniscid());

                // 3.1 处理经营异常名录移出
                int abnCount = removeAbnormalManagement(ent, today);
                abnRemoveCount += abnCount;

                // 3.2 处理严重违法记录移出
                int illegalCount = removeSeriousViolation(ent, today);
                illegalRemoveCount += illegalCount;

                // 3.3 处理行政处罚信用修复记录插入
                int penaltyCount = insertPenaltyCreditRepair(ent, today);
                penaltyRepairCount += penaltyCount;

                log.info("主体处理完成: PRIPID={}, 经营异常移出={}, 严重违法移出={}, 行政处罚信用修复={}",
                        ent.getPripid(), abnCount, illegalCount, penaltyCount);
            }

            long endTime = System.currentTimeMillis();
            log.info("==========注销主体自动移出任务执行完成==========");
            log.info("共处理注销主体{}个, 经营异常移出{}条, 严重违法移出{}条, 行政处罚信用修复{}条, 耗时{}ms",
                    cancelledEntList.size(), abnRemoveCount, illegalRemoveCount, penaltyRepairCount, (endTime - startTime));

        } catch (Exception e) {
            log.error("注销主体自动移出任务执行异常", e);
            throw e;
        } finally {
            redisService.remove(REDIS_LOCK);
        }
    }

    /**
     * 查询当天注销的市场主体
     *
     * @param today 当天日期
     * @return 注销主体列表
     */
    private List<EBaseInfo> queryCancelledEntities(LocalDate today) {
        LambdaQueryWrapper<EBaseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(EBaseInfo::getRegstate, "3", "4");
        // 核准日期(REGDATE)或最后更新日期包含当天
        String todayStr = today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 由于注销日期可能在不同字段，这里查询所有状态为注销的主体，再在业务层筛选
        wrapper.last("AND (TO_CHAR(REGDATE, 'YYYY-MM-DD') = '" + todayStr + "' " +
                "OR TO_CHAR(APPRDATE, 'YYYY-MM-DD') = '" + todayStr + "')");
        return eBaseInfoMapper.selectList(wrapper);
    }

    /**
     * 移出经营异常名录
     *
     * @param ent   市场主体
     * @param today 处理日期
     * @return 移出的记录数
     */
    private int removeAbnormalManagement(EBaseInfo ent, LocalDate today) {
        try {
            LambdaQueryWrapper<AoOpaDetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AoOpaDetail::getPripid, ent.getPripid());
            queryWrapper.isNull(AoOpaDetail::getRemdate); // 未移出

            List<AoOpaDetail> abnormalList = aoOpaDetailMapper.selectList(queryWrapper);
            if (abnormalList.isEmpty()) {
                log.debug("主体无未移出的经营异常记录: PRIPID={}", ent.getPripid());
                return 0;
            }

            Map<String, TRBaseCode> cd72 = trBaseCodeService.getBaseCodeMapFormCache("CD72");
            TRBaseCode cd727 = cd72.get("CD72");

            Date removeDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());

            for (AoOpaDetail abnormal : abnormalList) {
                LambdaUpdateWrapper<AoOpaDetail> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(AoOpaDetail::getBusexclist, abnormal.getBusexclist());
                updateWrapper.set(AoOpaDetail::getIsmove, "1"); // 已移出
                updateWrapper.set(AoOpaDetail::getRemdate, removeDate);
                updateWrapper.set(AoOpaDetail::getRemexcpres, cd727.getCode());
                updateWrapper.set(AoOpaDetail::getRemexcpresCn, cd727.getName());
                // 移出机关使用原列入机关或默认值
                String removeOrg = abnormal.getDecorg() != null ? abnormal.getDecorg() : DEFAULT_REMOVE_ORG;
                String removeOrgCn = abnormal.getDecorgCn() != null ? abnormal.getDecorgCn() : DEFAULT_REMOVE_ORG_CN;
                updateWrapper.set(AoOpaDetail::getRedecorg, removeOrg);
                updateWrapper.set(AoOpaDetail::getRedecorgCn, removeOrgCn);

                aoOpaDetailMapper.update(null, updateWrapper);
                log.debug("经营异常移出成功: BUSEXCLIST={}", abnormal.getBusexclist());
            }

            log.info("主体经营异常名录移出完成: PRIPID={}, 移出{}条", ent.getPripid(), abnormalList.size());
            return abnormalList.size();

        } catch (Exception e) {
            log.error("经营异常名录移出异常: PRIPID={}", ent.getPripid(), e);
            return 0;
        }
    }

    /**
     * 移出严重违法记录
     *
     * @param ent   市场主体
     * @param today 处理日期
     * @return 移出的记录数
     */
    private int removeSeriousViolation(EBaseInfo ent, LocalDate today) {
        try {
            LambdaQueryWrapper<ELiIlldisdetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ELiIlldisdetail::getPripid, ent.getPripid());
            queryWrapper.isNull(ELiIlldisdetail::getRemdate); // 未移出

            List<ELiIlldisdetail> illegalList = eliIlldisdetailMapper.selectList(queryWrapper);
            if (illegalList.isEmpty()) {
                log.debug("主体无未移出的严重违法记录: PRIPID={}", ent.getPripid());
                return 0;
            }

            Date removeDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());

            Map<String, TRBaseCode> cd74 = trBaseCodeService.getBaseCodeMapFormCache("CD74");
            TRBaseCode cd743 = cd74.get("3");

            for (ELiIlldisdetail illegal : illegalList) {
                LambdaUpdateWrapper<ELiIlldisdetail> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(ELiIlldisdetail::getIllid, illegal.getIllid());
                updateWrapper.set(ELiIlldisdetail::getRemdate, removeDate);
                updateWrapper.set(ELiIlldisdetail::getRemexcpres, cd743.getCode());
                updateWrapper.set(ELiIlldisdetail::getRemexcpresCn, cd743.getName());
                // 移出机关使用原列入机关或默认值
                String removeOrg = illegal.getDecorg() != null ? illegal.getDecorg() : DEFAULT_REMOVE_ORG;
                String removeOrgCn = illegal.getDecorgCn() != null ? illegal.getDecorgCn() : DEFAULT_REMOVE_ORG_CN;
                updateWrapper.set(ELiIlldisdetail::getRecorg, removeOrg);
                updateWrapper.set(ELiIlldisdetail::getRecorgCn, removeOrgCn);
                // 生成移出文号
                String removeDocNo = "REM" + today.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + IdUtil.simpleUUID().substring(0, 8).toUpperCase();
                updateWrapper.set(ELiIlldisdetail::getRedocnum, removeDocNo);

                eliIlldisdetailMapper.update(null, updateWrapper);
                log.debug("严重违法移出成功: ILLID={}", illegal.getIllid());
            }

            log.info("主体严重违法记录移出完成: PRIPID={}, 移出{}条", ent.getPripid(), illegalList.size());
            return illegalList.size();

        } catch (Exception e) {
            log.error("严重违法记录移出异常: PRIPID={}", ent.getPripid(), e);
            return 0;
        }
    }

    /**
     * 插入行政处罚信用修复记录
     *
     * @param ent   市场主体
     * @param today 处理日期
     * @return 插入的记录数
     */
    private int insertPenaltyCreditRepair(EBaseInfo ent, LocalDate today) {
        try {
            // 查询该主体的行政处罚记录
            LambdaQueryWrapper<EImCase> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EImCase::getPripid, ent.getPripid());

            List<EImCase> penaltyList = eImCaseMapper.selectList(queryWrapper);
            if (penaltyList.isEmpty()) {
                log.debug("主体无行政处罚记录: PRIPID={}", ent.getPripid());
                return 0;
            }

            Date repairDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());

            for (EImCase penalty : penaltyList) {
                // 检查是否已存在信用修复记录
                LambdaQueryWrapper<CaseCreInformation> existWrapper = new LambdaQueryWrapper<>();
                existWrapper.eq(CaseCreInformation::getCaseid, penalty.getCaseid());
                existWrapper.eq(CaseCreInformation::getPripid, ent.getPripid());
                int existCount = caseCreInformationMapper.selectCount(existWrapper);

                if (existCount > 0) {
                    log.debug("信用修复记录已存在, 跳过: CASEID={}", penalty.getCaseid());
                    continue;
                }

                // 创建新的信用修复记录
                CaseCreInformation repairRecord = new CaseCreInformation();
                repairRecord.setCasecreid(IdUtil.simpleUUID().replace("-", ""));
                repairRecord.setPripid(ent.getPripid());
                repairRecord.setEntname(ent.getEntname());
                repairRecord.setUniscid(ent.getUniscid());
                repairRecord.setCaseid(penalty.getCaseid());
                repairRecord.setRepairdate(repairDate);
                repairRecord.setRepauth(DEFAULT_REMOVE_ORG);
                repairRecord.setRepauthCn(DEFAULT_REMOVE_ORG_CN);
                repairRecord.setRepdate(repairDate);

                caseCreInformationMapper.insert(repairRecord);
                log.debug("行政处罚信用修复记录插入成功: CASECREID={}, CASEID={}", repairRecord.getCasecreid(), penalty.getCaseid());
            }

            log.info("主体行政处罚信用修复记录插入完成: PRIPID={}, 插入{}条", ent.getPripid(), penaltyList.size());
            return penaltyList.size();

        } catch (Exception e) {
            log.error("行政处罚信用修复记录插入异常: PRIPID={}", ent.getPripid(), e);
            return 0;
        }
    }
}
