package com.yolo.keyboard.job;

import cn.hutool.core.collection.CollUtil;
import com.yolo.keyboard.dal.dataobject.tenantbalance.TenantBalanceDO;
import com.yolo.keyboard.dal.dataobject.tenantbalancetransaction.TenantBalanceTransactionDO;
import com.yolo.keyboard.dal.dataobject.tenantcommission.KeyboardTenantCommissionDO;
import com.yolo.keyboard.dal.mysql.tenantbalance.TenantBalanceMapper;
import com.yolo.keyboard.dal.mysql.tenantbalancetransaction.TenantBalanceTransactionMapper;
import com.yolo.keyboard.dal.mysql.tenantcommission.KeyboardTenantCommissionMapper;
import com.yolo.keyboard.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.yolo.keyboard.framework.quartz.core.handler.JobHandler;
import com.yolo.keyboard.framework.tenant.core.aop.TenantIgnore;
import com.yolo.keyboard.utils.BizNoGenerator;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 分成可提现转换定时任务
 * 每小时执行一次，将满30天的分成金额转为可提现余额
 *
 * @author ziin
 */
@Component
@Slf4j
public class CommissionWithdrawableJob implements JobHandler {

    @Resource
    private KeyboardTenantCommissionMapper commissionMapper;

    @Resource
    private TenantBalanceMapper tenantBalanceMapper;

    @Resource
    private TenantBalanceTransactionMapper balanceTransactionMapper;

    private static final String WITHDRAWABLE_TYPE = "WITHDRAWABLE";

    @Override
    @TenantIgnore
    @Transactional(rollbackFor = Exception.class)
    public String execute(String param) {
        log.info("[CommissionWithdrawableJob] 开始执行分成可提现转换任务");

        LocalDateTime now = LocalDateTime.now();

        // 1. 查询已到可提现时间且未处理的分成记录
        List<KeyboardTenantCommissionDO> commissions = commissionMapper.selectList(
                new LambdaQueryWrapperX<KeyboardTenantCommissionDO>()
                        .le(KeyboardTenantCommissionDO::getWithdrawableAt, now)
                        .eq(KeyboardTenantCommissionDO::getWithdrawableProcessed, false)
                        .eq(KeyboardTenantCommissionDO::getStatus, "SETTLED")
        );

        if (CollUtil.isEmpty(commissions)) {
            log.info("[CommissionWithdrawableJob] 没有需要处理的分成记录");
            return "没有需要处理的分成记录";
        }

        // 2. 按租户分组汇总金额
        Map<Long, List<KeyboardTenantCommissionDO>> tenantCommissionsMap = commissions.stream()
                .collect(Collectors.groupingBy(KeyboardTenantCommissionDO::getTenantId));

        int tenantCount = 0;
        int commissionCount = 0;
        BigDecimal totalAmount = BigDecimal.ZERO;

        // 3. 逐个租户处理
        for (Map.Entry<Long, List<KeyboardTenantCommissionDO>> entry : tenantCommissionsMap.entrySet()) {
            Long tenantId = entry.getKey();
            List<KeyboardTenantCommissionDO> tenantCommissions = entry.getValue();

            // 计算该租户的总可提现金额
            BigDecimal tenantTotalAmount = tenantCommissions.stream()
                    .map(KeyboardTenantCommissionDO::getCommissionAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 更新租户可提现余额
            TenantBalanceDO balance = tenantBalanceMapper.selectById(tenantId);
            if (balance == null) {
                log.warn("[CommissionWithdrawableJob] 租户 {} 余额记录不存在，跳过", tenantId);
                continue;
            }

            BigDecimal currentWithdrawable = balance.getWithdrawableBalance() != null
                    ? balance.getWithdrawableBalance() : BigDecimal.ZERO;
            BigDecimal newWithdrawable = currentWithdrawable.add(tenantTotalAmount);
            balance.setWithdrawableBalance(newWithdrawable);
            tenantBalanceMapper.updateById(balance);

            // 创建余额交易记录
            String bizNo = BizNoGenerator.generate("WDB");
            TenantBalanceTransactionDO transaction = TenantBalanceTransactionDO.builder()
                    .bizNo(bizNo)
                    .points(tenantTotalAmount)
                    .balance(balance.getBalance())
                    .frozenAmt(balance.getFrozenAmt() != null ? balance.getFrozenAmt() : BigDecimal.ZERO)
                    .withdrawableBalance(newWithdrawable)
                    .tenantId(tenantId)
                    .type(WITHDRAWABLE_TYPE)
                    .description("分成转可提现")
                    .createdAt(now)
                    .remark("共 " + tenantCommissions.size() + " 笔分成转为可提现")
                    .build();
            balanceTransactionMapper.insert(transaction);

            // 标记分成记录为已处理
            for (KeyboardTenantCommissionDO commission : tenantCommissions) {
                commission.setWithdrawableProcessed(true);
                commission.setUpdatedAt(now);
                commissionMapper.updateById(commission);
            }

            tenantCount++;
            commissionCount += tenantCommissions.size();
            totalAmount = totalAmount.add(tenantTotalAmount);

            log.info("[CommissionWithdrawableJob] 处理租户 {}，分成 {} 笔，金额 {}",
                    tenantId, tenantCommissions.size(), tenantTotalAmount);
        }

        String result = String.format("处理租户 %d 个，分成记录 %d 条，总金额 %s",
                tenantCount, commissionCount, totalAmount.toPlainString());
        log.info("[CommissionWithdrawableJob] 任务执行完成: {}", result);
        return result;
    }
}
