package com.yd.csf.api.handler;

import com.alibaba.fastjson.JSON;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yd.common.enums.CommonEnum;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.feign.enums.OprSourceEnum;
import com.yd.csf.service.enums.RuleItemEnum;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.framework.config.LockExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 冷静期定时发送任务处理器
 */
@Component
@Slf4j
public class CalmSendJobHandler {

    @Resource
    private LockExecutor lockExecutor;

    @Resource
    private ICalmTaskService iCalmTaskService;
    @Resource
    private IAgentDetailFycService iAgentDetailFycService;
    @Resource
    private IAgentAccumulatedFycService iAgentAccumulatedFycService;
    @Resource
    private IAgentAccumulatedFycLogService iAgentAccumulatedFycLogService;

    /**
     * XXL-Job任务执行入口方法
     */
    @XxlJob("calmSendJobHandler")
    public void execute() throws Exception {
        LocalDateTime taskSendTime = LocalDateTime.now();
        String param = XxlJobHelper.getJobParam();
        log.info("开始冷静期定时发送任务，参数: {}", param);

        String taskBizId = param;
        CalmTask calmTask = iCalmTaskService.queryOne(taskBizId);
        log.info("根据冷静期定时发送任务业务ID查询冷静期定时任务信息: {}: {}", taskBizId, JSON.toJSONString(calmTask));

        if (Objects.isNull(calmTask)) {
            XxlJobHelper.log("冷静期定时发送任务不存在: " + taskBizId);
            XxlJobHelper.handleFail("冷静期定时发送任务不存在");
            return;
        }

        // 更新任务状态
        calmTask.setExecutionStatus("2");
        iCalmTaskService.saveOrUpdate(calmTask);

        // 更新积分明细状态
        AgentDetailFyc agentDetailFyc = iAgentDetailFycService.queryOne(calmTask.getDetailFycBizId());
        if (agentDetailFyc != null) {
            agentDetailFyc.setStatus(1);
            iAgentDetailFycService.saveOrUpdate(agentDetailFyc);
        }

        // 使用分布式锁保护积分总表更新（流式调用）
        String brokerBizId = calmTask.getBrokerBizId();
        String lockKey = "calm:accumulated:lock:" + brokerBizId;

        lockExecutor.executeWithLock(lockKey, () -> {
            // 锁内业务逻辑
            updateAccumulatedFyc(calmTask);
        });
    }

    /**
     * 积分总表累计更新逻辑（原 execute 内的积分部分）
     * 在分布式锁保护下执行，确保同一经纪人串行处理
     */
    private void updateAccumulatedFyc(CalmTask calmTask) {
        String brokerBizId = calmTask.getBrokerBizId();
        AgentAccumulatedFyc agentAccumulatedFyc = iAgentAccumulatedFycService.queryOne(brokerBizId);
        if (agentAccumulatedFyc == null) {
            log.warn("经纪人积分总表记录不存在，brokerBizId: {}", brokerBizId);
            return;
        }

        // 安全获取任务佣金增量值
        BigDecimal fycValue = calmTask.getAfterFyc() == null ? BigDecimal.ZERO : calmTask.getAfterFyc();

        // 安全获取原有字段值（null -> 0）
        BigDecimal noEffectOld = nvl(agentAccumulatedFyc.getNoEffect());
        BigDecimal effectOld = nvl(agentAccumulatedFyc.getEffect());
        BigDecimal firstCommissionOld = nvl(agentAccumulatedFyc.getFirstCommission());
        BigDecimal noFirstCommissionOld = nvl(agentAccumulatedFyc.getNoFirstCommission());
        BigDecimal rycOld = nvl(agentAccumulatedFyc.getRyc());
        BigDecimal noRycOld = nvl(agentAccumulatedFyc.getNoRyc());
        BigDecimal firstSalesCommissionOld = nvl(agentAccumulatedFyc.getFirstSalesCommission());
        BigDecimal noFirstSalesCommissionOld = nvl(agentAccumulatedFyc.getNoFirstSalesCommission());

        // 未生效/已生效累计积分
        BigDecimal noEffect = noEffectOld.subtract(fycValue);
        agentAccumulatedFyc.setNoEffect(noEffect.max(BigDecimal.ZERO));
        BigDecimal effect = effectOld.add(fycValue);
        agentAccumulatedFyc.setEffect(effect);
        agentAccumulatedFyc.setTotalFyc(agentAccumulatedFyc.getNoEffect().add(agentAccumulatedFyc.getEffect()));

        if (calmTask.getFortunePeriod() != null && calmTask.getFortunePeriod() == 1) {
            // 首期佣金
            BigDecimal firstCommission = firstCommissionOld.add(fycValue);
            agentAccumulatedFyc.setFirstCommission(firstCommission);
            BigDecimal noFirstCommission = noFirstCommissionOld.subtract(fycValue);
            agentAccumulatedFyc.setNoFirstCommission(noFirstCommission.max(BigDecimal.ZERO));

            if (RuleItemEnum.SALES.getRuleItemBizId().equals(calmTask.getRuleItemBizId())) {
                BigDecimal firstSalesCommission = firstSalesCommissionOld.add(fycValue);
                agentAccumulatedFyc.setFirstSalesCommission(firstSalesCommission);
                BigDecimal noFirstSalesCommission = noFirstSalesCommissionOld.subtract(fycValue);
                agentAccumulatedFyc.setNoFirstSalesCommission(noFirstSalesCommission.max(BigDecimal.ZERO));
            }
        } else {
            // 非首期佣金
            BigDecimal ryc = rycOld.add(fycValue);
            agentAccumulatedFyc.setRyc(ryc);
            BigDecimal noRyc = noRycOld.subtract(fycValue);
            agentAccumulatedFyc.setNoRyc(noRyc.max(BigDecimal.ZERO));
        }

        // 晋升职级累计积分
        BigDecimal initEffect = nvl(agentAccumulatedFyc.getInitEffect());
        BigDecimal firstSalesCommission = nvl(agentAccumulatedFyc.getFirstSalesCommission());
        BigDecimal promotion = initEffect.add(firstSalesCommission);
        agentAccumulatedFyc.setPromotion(promotion.max(BigDecimal.ZERO));

        agentAccumulatedFyc.setLastCalcDate(LocalDateTime.now());
        iAgentAccumulatedFycService.saveOrUpdate(agentAccumulatedFyc);

        // 新增积分总表日志
        AgentAccumulatedFycLog logObj = new AgentAccumulatedFycLog();
        BeanUtils.copyProperties(agentAccumulatedFyc, logObj);
        logObj.setId(null);
        logObj.setFycBizId(agentAccumulatedFyc.getFycBizId());
        logObj.setFycLogBizId(RandomStringGenerator.generateBizId16(
                CommonEnum.UID_TYPE_AGENT_ACCUMULATED_FYC_LOG.getCode()));
        logObj.setSourceType(OprSourceEnum.CALM_TASK_FREEZE.getItemValue());
        logObj.setCreateTime(LocalDateTime.now());
        logObj.setUpdateTime(LocalDateTime.now());
        iAgentAccumulatedFycLogService.saveOrUpdate(logObj);

        log.debug("经纪人积分累算完成，brokerBizId: {}, 本次增量: {}", brokerBizId, fycValue);
    }

    /**
     * BigDecimal 空值安全转零
     */
    private BigDecimal nvl(BigDecimal val) {
        return val == null ? BigDecimal.ZERO : val;
    }
}