package com.bonus.material.settlement.service.impl;

import com.bonus.common.biz.constant.GlobalConstants;
import com.bonus.common.biz.enums.TmTaskTypeEnum;
import com.bonus.common.biz.enums.WorkFlowStatusEnum;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.basic.mapper.BmFileInfoMapper;
import com.bonus.material.settlement.domain.SltAgreementReduce;
import com.bonus.material.settlement.mapper.SltAgreementReduceMapper;
import com.bonus.material.settlement.service.ISltAgreementReduceService;
import com.bonus.material.work.domain.dto.SysWorkflowAuditDto;
import com.bonus.material.work.mapper.SysWorkflowRecordMapper;
import com.bonus.material.work.service.SysWorkflowRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 结算协议减免Service业务层处理
 *
 * @author yuecs
 * @date 2025-10-16
 */
@Service
@Slf4j
public class SltAgreementReduceServiceImpl implements ISltAgreementReduceService {

    @Resource
    private SltAgreementReduceMapper sltAgreementRecudceMapper;

    @Resource
    private BmFileInfoMapper bmFileInfoMapper;

    @Resource
    private SysWorkflowRecordService workflowRecordService;

    @Resource
    private SysWorkflowRecordMapper workflowRecordMapper;

    @Override
    public List<SltAgreementReduce> selectSltAgreementReduceList(SltAgreementReduce sltAgreement) {
        return sltAgreementRecudceMapper.selectSltAgreementReduceList(sltAgreement);
    }

    @Override
    public List<SltAgreementReduce> getApplyReduceList(SltAgreementReduce sltAgreement) {
        return sltAgreementRecudceMapper.getApplyReduceList(sltAgreement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 对所有异常回滚
    public AjaxResult addApply(SltAgreementReduce sltAgreement) {
        List<SltAgreementReduce> list;
        try {
            // 初始化 SltAgreementReduce 对象
            initSltAgreement(sltAgreement);
            // 计算减免区间
            List<SltAgreementReduce> applyReduction = applyReduction(sltAgreement);

            if (!applyReduction.isEmpty()) {
                list = applyReduction;
            } else {
                list = null;
            }

            if (null != list) {
                sltAgreement.setCreator(SecurityUtils.getLoginUser().getUserid().toString());
                // 插入外层任务信息
                Long rs = sltAgreementRecudceMapper.insertReduce(sltAgreement);
                Long taskId = sltAgreement.getId();
                if (null != rs && rs > 0 && null != taskId && taskId > 0) {
                    workflowRecordService.addSysWorkflowRecord(Math.toIntExact(taskId), sltAgreement.getCode(), TmTaskTypeEnum.TM_TASK_PART_TYPE.getTaskTypeId());
                } else {
                    throw new RuntimeException("新增失败");
                }
                AtomicBoolean addFileInfoResult = new AtomicBoolean(false);
                if (sltAgreement.getBmFileInfos() != null && !sltAgreement.getBmFileInfos().isEmpty()) {
                    sltAgreement.getBmFileInfos().removeIf(Objects::isNull);
                    sltAgreement.getBmFileInfos().forEach(bmFileInfo -> {
                        bmFileInfo.setModelId(taskId);
                        bmFileInfo.setCreateTime(DateUtils.getNowDate());
                        addFileInfoResult.set(bmFileInfoMapper.insertBmFileInfo(bmFileInfo) > 0);
                    });

                }
                if (rs > GlobalConstants.INT_0) {
                    // 批量插入明细
                    List<SltAgreementReduce> detailList = list.stream()
                            .peek(detail -> detail.setId(taskId))
                            .collect(Collectors.toList());
                    sltAgreementRecudceMapper.insertBatchReduceDetail(detailList);
                }
            } else {
                return AjaxResult.warn("检索历史申请减免区间数据，已申请减免，请勿在提交申请单！");
            }

            return AjaxResult.success();
        } catch (DataAccessException e) {
            // 记录详细的数据库操作异常日志
            log.error("数据库操作失败: {}", e.getMessage(), e);
            return AjaxResult.error("系统错误, 数据库操作失败");
        } catch (Exception e) {
            // 记录其他异常日志
            log.error("系统错误: {}", e.getMessage(), e);
            return AjaxResult.error("系统错误, " + e.getMessage());
        }
    }

    @Override
    public List<SltAgreementReduce> selectByMatype(SltAgreementReduce sltAgreement) {
        return sltAgreementRecudceMapper.selectByMatype(sltAgreement);
    }

    @Override
    public List<SltAgreementReduce> selectByMaModel(SltAgreementReduce sltAgreement) {
        return sltAgreementRecudceMapper.selectByMaModel(sltAgreement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editApply(SltAgreementReduce sltAgreement) {
        try {
            //先删除详情表和附件表数据
            sltAgreementRecudceMapper.deleteReduceDetail(sltAgreement.getId());

            List<SltAgreementReduce> list  = sltAgreement.getDetailList();
            // 初始化 SltAgreementReduce 对象
            initSltAgreement(sltAgreement);

            List<SltAgreementReduce> applyReduction = applyReduction(sltAgreement);

            if (applyReduction.size() > 0 && applyReduction!= null) {
                list = applyReduction;
            }else{
                list = null;
            }
            if(list != null){
                Long rs = sltAgreementRecudceMapper.updateReduce(sltAgreement);
                Long id = sltAgreement.getId();
                AtomicBoolean addFileInfoResult = new AtomicBoolean(false);
                //删除之前的附件
                bmFileInfoMapper.deleteBmFileInfoByModelId(id);
                if(sltAgreement.getBmFileInfos()!=null){
                    sltAgreement.getBmFileInfos().forEach(bmFileInfo -> {
                        bmFileInfo.setModelId(id);
                        bmFileInfo.setCreateTime(DateUtils.getNowDate());
                        addFileInfoResult.set(bmFileInfoMapper.insertBmFileInfo(bmFileInfo) > 0);
                    });

                }
                if (list != null) {
                    // 批量插入明细
                    List<SltAgreementReduce> detailList = list.stream()
                            .peek(detail -> detail.setId(id))
                            .collect(Collectors.toList());
                    sltAgreementRecudceMapper.insertBatchReduceDetail(detailList);
                }
            }else{
                //回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return  AjaxResult.warn("检索历史申请减免区间数据，已申请减免，请勿在提交申请单！");
            }
            return AjaxResult.success();
        } catch (DataAccessException e) {
            // 记录详细的数据库操作异常日志
            log.error("数据库操作失败: {}", e.getMessage(), e);
            return AjaxResult.error("系统错误, 数据库操作失败");
        } catch (Exception e) {
            // 记录其他异常日志
            log.error("系统错误: {}", e.getMessage(), e);
            return AjaxResult.error("系统错误, " + e.getMessage());
        }
    }

    @Override
    public List<SltAgreementReduce> selectAuditReduceList(SltAgreementReduce sltAgreement) {
        return sltAgreementRecudceMapper.selectAuditReduceList(sltAgreement);
    }

    /**
     * 审核
     * @param workflowAuditDto 费用减免审核
     * @return AjaxResult结构 返回审核结果
     */
    @Override
    public AjaxResult audit(SysWorkflowAuditDto workflowAuditDto) {
        if (null == workflowAuditDto || null == workflowAuditDto.getTaskId()) {
            return AjaxResult.error("参数为空");
        }
        SysWorkflowAuditDto workflowRecordInfo = workflowRecordMapper.getSysWorkflowRecodeByTaskId(workflowAuditDto.getTaskId());
        if (null == workflowRecordInfo) {
            return AjaxResult.error("审核记录不存在");
        }
        // 判断审核流是否执行完毕
        if (Objects.equals(workflowRecordInfo.getWorkflowStatus(), WorkFlowStatusEnum.AUDIT_FINISH.getCode())) {
            // 判断传入任务ID的类型，类型异常直接终止
            if (Objects.equals(workflowRecordInfo.getTaskType(), TmTaskTypeEnum.TM_TASK_PART_TYPE.getTaskTypeId())) {
                try {
                    SltAgreementReduce sltAgreement = new SltAgreementReduce();
                    sltAgreement.setId(Long.valueOf(workflowAuditDto.getTaskId()));
                    sltAgreement.setStatus("1");
                    sltAgreementRecudceMapper.updateReduce(sltAgreement);
                    return AjaxResult.success("执行完成");
                } catch (Exception e) {
                    return AjaxResult.error("修改任务状态失败,SQL执行异常");
                }
            } else {
                return AjaxResult.error("该业务非费用减免任务,无法执行操作！");
            }
        } else {
            return AjaxResult.error("审批流程未执行完毕，请检查!");
        }
    }

    private void initSltAgreement(SltAgreementReduce sltAgreement) {
        sltAgreement.setCode(generateCode());
        sltAgreement.setCreateTime(new Date());
    }


    public List<SltAgreementReduce> applyReduction(SltAgreementReduce sltAgreement) {
        // 初始化结果列表
        List<SltAgreementReduce> temp = new ArrayList<>();
        // 遍历申请减免的每个区间

        for (SltAgreementReduce current : sltAgreement.getDetailList()) {
            if (current.getReduceStartTime() != null && current.getReduceEndTime() != null) {
                // 将当前区间添加到结果列表中

                // 查询与当前区间有重叠的历史减免记录
                List<SltAgreementReduce> historyReductions = sltAgreementRecudceMapper.findOverlappingReductions(current);

                if (null != historyReductions && !historyReductions.isEmpty()) {
                    // 对比并去掉重叠部分
                    for (SltAgreementReduce history : historyReductions) {

                        // 如果当前区间与历史区间没有重叠，直接保留
                        if (current.getReduceEndTime().before(history.getReduceStartTime()) || current.getReduceStartTime().after(history.getReduceEndTime())) {
                            temp.add(current);
                        } else {
                            // 如果有重叠，拆分当前区间
                            if (current.getReduceStartTime().before(history.getReduceStartTime())) {
                                // 生成新的区间：申请开始时间到历史开始时间的前一天
                                //计算新的租赁情况
                                current.setReduceStartTime(current.getReduceStartTime());
                                current.setReduceEndTime(new Date(history.getReduceStartTime().getTime() - 86400000));
                                long days = (history.getReduceStartTime().getTime() - current.getReduceStartTime().getTime()) / (24 * 60 * 60 * 1000) +1;
                                BigDecimal num = current.getNum();
                                BigDecimal leasePrice = current.getLeasePrice();
                                current.setLeasePrice(leasePrice);
                                BigDecimal leaseMoney = new BigDecimal(days).multiply(num).multiply(leasePrice);
                                current.setLeaseMoney(leaseMoney);
                                temp.add(
                                        current
                                );
                            }
                            if (current.getReduceEndTime().after(history.getReduceEndTime())) {
                                // 生成新的区间：历史结束时间的后一天到申请结束时间
                                //计算新的租赁情况
                                current.setStartTime( new Date(history.getReduceEndTime().getTime() + 86400000));
                                current.setEndTime( current.getReduceEndTime());
                                long days = (current.getReduceEndTime().getTime() - history.getReduceEndTime().getTime()) / (24 * 60 * 60 * 1000) +1;
                                BigDecimal num = current.getNum();
                                BigDecimal leasePrice = current.getLeasePrice();
                                current.setLeasePrice(leasePrice);
                                BigDecimal leaseMoney = new BigDecimal(days).multiply(num).multiply(leasePrice);
                                current.setLeaseMoney(leaseMoney);
                                temp.add(
                                        current
                                );
                            }
                        }

                    }
                }else{
                    temp.add(current);
                }

            }
        }
        return temp;
    }



    public String generateCode() {
        // 获取当前日期，格式为 YYYYMMDD
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // 获取当前日期，格式为 YYY-YM-MDD
        // 查询当前最大单号
        String maxCode = sltAgreementRecudceMapper.getMaxCode(date);

        // 生成新单号
        String newCode;
        if (maxCode == null) {
            // 如果当天没有单号，生成第一个单号
            newCode = "JM" + date + "-0001";
        } else {
            // 提取序号部分并加 1
            int lastNumber = Integer.parseInt(maxCode.substring(maxCode.length() - 4));
            // 补零到 4 位
            String newNumber = String.format("%04d", lastNumber + 1);
            newCode = "JM" + date + "-" + newNumber;
        }

        return newCode;
    }
}
