package com.ai.da.service.impl;

import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.constant.AffiliateConstants;
import com.ai.da.common.constant.CommonConstant;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.PageBaseResponse;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.common.utils.RedisUtilEnhance;
import com.ai.da.common.utils.SendEmailUtil;
import com.ai.da.mapper.primary.*;
import com.ai.da.mapper.primary.entity.*;
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
import com.ai.da.model.dto.AffiliateQueryDTO;
import com.ai.da.model.vo.AffiliateInvitationDetailsVO;
import com.ai.da.model.vo.AffiliateVO;
import com.ai.da.model.vo.AuthPrincipalVo;
import com.ai.da.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.cj.util.StringUtils;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ai.da.common.utils.RedisUtil.AFFILIATE_LINK_VIEW_KEY;

@Service
@Slf4j
public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate> implements AffiliateService {

    @Resource
    private OrderInfoService orderInfoService;
    @Resource
    private AccountService accountService;
    @Resource
    private PaymentInfoService paymentInfoService;
    @Resource
    private SubscriptionInfoMapper subscriptionInfoMapper;
    @Resource
    private ReferralService referralService;
    @Resource
    private ReferralMapper referralMapper;
    @Resource
    private StripeService stripeService;
    @Resource
    private ProductCouponsMapper productCouponsMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private EmailService emailService;

    // 推广者注册
    public Boolean registerAsAnAffiliate(String promotionMethod){
        AuthPrincipalVo userHolder = UserContext.getUserHolder();
        // 判断该用户是否已注册
        QueryWrapper<Affiliate> qw = new QueryWrapper<>();
        qw.eq("account_id", userHolder.getId());
        Affiliate affiliate = baseMapper.selectOne(qw);
        if (Objects.isNull(affiliate)){
            affiliate = new Affiliate();
            affiliate.setAccountId(userHolder.getId());
            affiliate.setStatus("Pending");
            affiliate.setCreateTime(LocalDateTime.now());
            affiliate.setPromotionMethod(promotionMethod);
            baseMapper.insert(affiliate);
            // 邮件通知审批者
            String merchantEmail = "kimwong@code-create.com.hk";
            String developer = "xupei3360@163.com";
            String[] receiverEmail = {/*merchantEmail,*/ developer};
            SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
//            emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
        }else {
            throw new BusinessException("You have registered an Affiliate", ResultEnum.PROMPT.getCode());
        }
        return true;
    }

    public PageBaseResponse<AffiliateVO> getAffiliateList(AffiliateQueryDTO affiliateQueryDTO){
        log.info("parameter => {}", affiliateQueryDTO.toString());

        int offset = (affiliateQueryDTO.getPage() - 1) * affiliateQueryDTO.getSize();
        String orderBy = affiliateQueryDTO.getOrderBy() == null ? "id" :
                affiliateQueryDTO.getOrderBy().equals("id") ? "id" :
                        affiliateQueryDTO.getOrderBy().equals("totalIncome") ? "total_earnings" :
                                "create_time";
        List<AffiliateVO> affiliateList = baseMapper.getAffiliateList(affiliateQueryDTO.getStatus(),
                affiliateQueryDTO.getStartTime(),
                affiliateQueryDTO.getEndTime(),
                affiliateQueryDTO.getOrder(),
                affiliateQueryDTO.getAffiliateId(),
                orderBy,
                affiliateQueryDTO.getSize(),
                offset
        );
        if (CollectionUtils.isEmpty(affiliateList)) {
            return PageBaseResponse.success(new Page<>());
        }else {
            int totalCount = baseMapper.queryAffiliateTotalCount(affiliateQueryDTO.getStatus(),
                    affiliateQueryDTO.getStartTime(),
                    affiliateQueryDTO.getEndTime(),
                    affiliateQueryDTO.getAffiliateId()
            );
            IPage<AffiliateVO> orderListVOIPage = new Page<>();
            Integer size = affiliateQueryDTO.getSize();
            orderListVOIPage.setSize(size);
            orderListVOIPage.setRecords(affiliateList);
            orderListVOIPage.setCurrent(affiliateQueryDTO.getPage());
            orderListVOIPage.setPages((long)Math.ceil((double) totalCount / size));
            orderListVOIPage.setTotal(totalCount);
            return PageBaseResponse.success(orderListVOIPage);
        }
        /*QueryWrapper<Affiliate> qw = new QueryWrapper<>();
        qw.eq(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getStatus()), "status", affiliateQueryDTO.getStatus())
                .gt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getStartTime()), "create_time", affiliateQueryDTO.getStartTime())
                .lt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getEndTime()), "create_time", affiliateQueryDTO.getEndTime())
                .eq(!Objects.isNull(affiliateQueryDTO.getAffiliateId()), "id", affiliateQueryDTO.getAffiliateId())
                .orderByDesc(affiliateQueryDTO.getOrder().equals("DESC"), "create_time");
        Page<Affiliate> affiliatePage = baseMapper.selectPage(new Page<>(affiliateQueryDTO.getPage(), affiliateQueryDTO.getSize()), qw);
        affiliatePage.convert((Function<Affiliate, AffiliateVO>) affiliate-> {
            AffiliateVO affiliateVO = CopyUtil.copyObject(affiliate, AffiliateVO.class);
            affiliateVO.setUsername();
        });
        return affiliatePage;*/
    }

    public AffiliateVO personalAffiliateCenter(){
        QueryWrapper<Affiliate> qw = new QueryWrapper<>();
        Long accountId = UserContext.getUserHolder().getId();
        qw.eq("account_id", accountId);
        Affiliate affiliate = baseMapper.selectOne(qw);
        AffiliateVO affiliateVO = CopyUtil.copyObject(affiliate, AffiliateVO.class);
        return affiliateVO;
    }

    public BigDecimal[] getPersonalMonthlyIncome(int year){
        Long accountId = UserContext.getUserHolder().getId();
        List<Map<String, Object>> personalMonthlyIncome = referralMapper.getPersonalMonthlyIncome(accountId, year);
        BigDecimal[] commissions = new BigDecimal[12];
        Arrays.fill(commissions, BigDecimal.ZERO);
        personalMonthlyIncome.forEach(income -> {
            int month = Integer.parseInt(income.get("yearMonth").toString());
            commissions[month-1] = (BigDecimal) income.get("totalCommission");
        });

        return commissions;
    }

    // 审批申请
    public Boolean applicationApproval(Long id, Boolean isApproved, Float commission){
        Affiliate affiliate = baseMapper.selectById(id);

        // 1、更新db状态
        if (isApproved){
            // 更新状态
            affiliate.setStatus("Active");
            affiliate.setApproved(true);
            affiliate.setLink(CommonConstant.AFFILIATE_LINK + affiliate.getId());
            if (Objects.isNull(commission)) {
                // 未设置佣金比例的情况下，默认25%
                affiliate.setCommissionPercent(20f);
            } else {
                affiliate.setCommissionPercent(commission);
            }
        } else {
            affiliate.setStatus("Refused");
            affiliate.setApproved(false);
        }
        affiliate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(affiliate);

        // 2、将批准结果邮件通知用户
        Account account = accountService.getById(affiliate.getAccountId());
        String[] userEmail = {account.getUserEmail()};
        String userName = account.getUserName();
        AffiliateEmailParamsDTO affiliateEmailParamsDTO = new AffiliateEmailParamsDTO(userName);
        if (isApproved){
            affiliateEmailParamsDTO.setInvitationId(affiliate.getId());
            SendEmailUtil.affiliateEmailReminder(userEmail, affiliateEmailParamsDTO, "accepted");
//            emailService.affiliateEmailReminder(Collections.singletonList(account.getUserEmail()), new AffiliateEmailParamsDTO(userName), "accepted");
        }else {
            SendEmailUtil.affiliateEmailReminder(userEmail, affiliateEmailParamsDTO, "refused");
//            emailService.affiliateEmailReminder(Collections.singletonList(account.getUserEmail()), new AffiliateEmailParamsDTO(userName), "refused");
        }
        return true;
    }

    public void editAffiliate(Long id, Float commission, String operationType) {
        // 参数验证
        if (id == null) {
            throw new BusinessException("affiliate.id.cannot.be.null");
        }

        Affiliate affiliate = baseMapper.selectById(id);
        if (affiliate == null) {
            log.warn("未知affiliate id: {}", id); // 使用warn级别更合适
            throw new BusinessException("unknown.affiliate");
        }

        // 构建更新条件
        UpdateWrapper<Affiliate> updateWrapper = buildUpdateWrapper(affiliate, commission, operationType);
        baseMapper.update(null, updateWrapper);
    }

    private UpdateWrapper<Affiliate> buildUpdateWrapper(Affiliate affiliate, Float commission, String operationType) {
        UpdateWrapper<Affiliate> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(Affiliate::getId, affiliate.getId())
                .set(Affiliate::getUpdateTime, LocalDateTime.now());

        // 处理佣金更新
        handleCommissionUpdate(affiliate, commission, updateWrapper);

        // 处理操作类型
        if (!StringUtil.isNullOrEmpty(operationType)) {
            handleOperationType(affiliate, operationType, updateWrapper);
        }

        return updateWrapper;
    }

    private void handleCommissionUpdate(Affiliate affiliate, Float commission,
                                        UpdateWrapper<Affiliate> updateWrapper) {
        if (commission != null && !Objects.equals(affiliate.getCommissionPercent(), commission)) {
            updateWrapper.lambda().set(Affiliate::getCommissionPercent, commission);
        }
    }

    private void handleOperationType(Affiliate affiliate, String operationType,
                                     UpdateWrapper<Affiliate> updateWrapper) {
        switch (operationType) {
            case AffiliateConstants.STATUS_DELETE:
                updateWrapper.lambda()
                        .set(Affiliate::getStatus, AffiliateConstants.STATUS_DELETE)
                        .set(Affiliate::getIsDeleted, AffiliateConstants.DELETED);
                break;

            case AffiliateConstants.STATUS_ACTIVE:
            case AffiliateConstants.STATUS_INACTIVE:
                updateWrapper.lambda().set(Affiliate::getStatus, operationType);
                // 激活时生成链接
                if (AffiliateConstants.STATUS_ACTIVE.equals(operationType) &&
                        StringUtil.isNullOrEmpty(affiliate.getLink())) {
                    updateWrapper.lambda().set(Affiliate::getLink,
                            CommonConstant.AFFILIATE_LINK + affiliate.getId());
                }
                break;

            default:
                throw new BusinessException("unknown.operationType");
        }
    }

    // 定时计算佣金
    public void updateAffiliateInfoWithPayment(){
        // id存redis
        String lastTime = redisUtil.getFromString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME);
        String currentTime = LocalDateTime.now().toString();
        // 1、查上次更新之后有无新订单
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PaymentInfo::getTradeState, "paid")
                .and(wrapper -> wrapper
                        .eq(PaymentInfo::getType,"new")
                        .or()
                        .eq(PaymentInfo::getType, "manual"));
        if (!StringUtil.isNullOrEmpty(lastTime)){
            queryWrapper.lambda().gt(PaymentInfo::getCreateTime, lastTime);
        }

        List<PaymentInfo> paymentInfos = paymentInfoService.getBaseMapper().selectList(queryWrapper);
        if (!paymentInfos.isEmpty()){
            paymentInfos.forEach(paymentInfo -> {
                // 2、根据order_no查付款用户id
                OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(paymentInfo.getOrderNo());
                if (Objects.isNull(orderInfo)){
                    return;
                }
                Long accountId = orderInfo.getAccountId();
                // 3、查该用户之前是否有初次订阅的订单
                QueryWrapper<OrderInfo> qwOrderInfo = new QueryWrapper<>();
                qwOrderInfo.eq("account_id", accountId).eq("is_first_subscription", 1);
                List<OrderInfo> orderInfos = orderInfoService.getBaseMapper().selectList(qwOrderInfo);
                // 该用户首次订阅（非首次订阅，不分配佣金）
                if (orderInfos.isEmpty()){
                    // 查询是否绑定affiliateId
                    Account account = accountService.getById(accountId);
                    if (!Objects.isNull(account.getInvitationCode())){
                        log.info("结算订单id为{}的佣金", orderInfo.getId());
                        // 3、若有, 直接更新affiliate的所得
                        Affiliate affiliate = baseMapper.selectById(account.getInvitationCode());
                        if (Objects.isNull(affiliate)){
                            log.error("未知affiliate Id:{}, 关联订单：{}", account.getInvitationCode(), orderInfo.getOrderNo());
                            return;
                        }
                        Float payerTotal = paymentInfo.getPayerTotal();

                        if (payerTotal > 0){
                            // 分配新用户首次订阅所付费用 预设的佣金比例 作为佣金
                            // 逻辑修改。只有当该笔referral被审批通过后才被计算为推广者的佣金
                            BigDecimal commission = BigDecimal.valueOf(payerTotal).multiply(BigDecimal.valueOf(affiliate.getCommissionPercent() / 100));
                            /*BigDecimal monthlyEarning = BigDecimal.valueOf(affiliate.getMonthlyEarnings()).add(commission);
                            BigDecimal unpaidEarnings = BigDecimal.valueOf(affiliate.getUnpaidEarnings()).add(commission);
                            int visits = affiliate.getVisits() + 1;
                            affiliate.setMonthlyEarnings(monthlyEarning.floatValue());
                            affiliate.setUnpaidEarnings(unpaidEarnings.floatValue());
                            affiliate.setVisits(visits);
                            affiliate.setUpdateTime(LocalDateTime.now());
                            baseMapper.updateById(affiliate);*/

                            orderInfo.setIsCommissionCalculated((byte)1);

                            // 4、添加到referral
                            Referral referral = new Referral();
                            referral.setAffiliateId(affiliate.getId());
                            referral.setAffiliateAccountId(affiliate.getAccountId());
                            referral.setInviteeAccountId(accountId);
                            referral.setAmount(BigDecimal.valueOf(payerTotal));
                            referral.setPaymentInfoId(paymentInfo.getId());
                            referral.setPaymentTime(paymentInfo.getCreateTime());
                            referral.setCommission(BigDecimal.valueOf(commission.floatValue()));
                            referral.setCommissionPercent(affiliate.getCommissionPercent());
                            referral.setStatus("Pending");
                            referral.setCreateTime(LocalDateTime.now());
                            int insert = referralService.getBaseMapper().insert(referral);
                            log.info("向Referral中插入 {} 条数据", insert);
                        }
                    }
                    orderInfo.setIsFirstSubscription((byte)1);
                    orderInfo.setUpdateTime(LocalDateTime.now());
                    orderInfoService.updateById(orderInfo);
                }
            });
        }
        redisUtil.addToString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME, currentTime);
    }

    public Boolean affiliateLinkViewsIncrease(Long affiliateId) {
        redisUtil.increaseAffiliateLinkViewCount(affiliateId);
        return Boolean.TRUE;
    }

    private Long getAffiliateLinkViewCount(Long affiliateId) {
        return redisUtil.getAffiliateLinkViewCount(affiliateId);
    }

    @Resource
    private RedisUtilEnhance redisUtilEnhance;

    public void syncLinkViewCountToDB() {
        // 1、获取当前所有激活状态的affiliate
        List<Affiliate> affiliateList = baseMapper.selectList(new QueryWrapper<Affiliate>().lambda().eq(Affiliate::getStatus, "Active"));

        // 2、获取redis中各自的viewCount
        for (Affiliate affiliate : affiliateList){
            String redisKey = AFFILIATE_LINK_VIEW_KEY + affiliate.getId();

            // 原子性获取并重置为0
            Long redisCount = redisUtilEnhance.getAndSetKey(redisKey, 0L);

            if (redisCount != null && redisCount > 0) {
                // 累加到数据库
                baseMapper.update(
                        null,
                        new UpdateWrapper<Affiliate>()
                                .setSql("visits = visits + " + redisCount)
                                .set("update_time", LocalDateTime.now())
                                .eq("id", affiliate.getId())
                );
            }
        }
    }

    // 查看每个affiliate带来收入的详情
    @Override
    public IPage<AffiliateInvitationDetailsVO> getEachAffiliateGeneratedRevenue(AffiliateQueryDTO affiliateQueryDTO) {
        if (Objects.isNull(affiliateQueryDTO.getAffiliateId())){
            throw new BusinessException("Please specify the affiliate ID.", ResultEnum.PROMPT.getCode());
        }

        QueryWrapper<Referral> referralQueryWrapper = new QueryWrapper<>();
        referralQueryWrapper
                .gt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getStartTime()), "create_time", affiliateQueryDTO.getStartTime())
                .lt(!StringUtils.isNullOrEmpty(affiliateQueryDTO.getEndTime()), "create_time", affiliateQueryDTO.getEndTime())
                .eq(!Objects.isNull(affiliateQueryDTO.getAffiliateId()), "affiliate_id", affiliateQueryDTO.getAffiliateId())
                .orderByDesc(affiliateQueryDTO.getOrder().equals("DESC"), "create_time");
        IPage<Referral> affiliateIncomePage = referralMapper.selectPage(new Page<>(affiliateQueryDTO.getPage(), affiliateQueryDTO.getSize()), referralQueryWrapper);
        return affiliateIncomePage.convert((Function<Referral, AffiliateInvitationDetailsVO>) affiliateIncome -> {
            AffiliateInvitationDetailsVO affiliateInvitationDetailsVO = CopyUtil.copyObject(affiliateIncome, AffiliateInvitationDetailsVO.class);
            affiliateInvitationDetailsVO.setAccountId(affiliateIncome.getInviteeAccountId());
            affiliateInvitationDetailsVO.setUsername(accountService.getBaseMapper().selectById(affiliateIncome.getInviteeAccountId()).getUserName());
            affiliateInvitationDetailsVO.setFirstSubscriptionPaymentAmount(affiliateIncome.getAmount());
            affiliateInvitationDetailsVO.setCommission(affiliateIncome.getCommission());
            affiliateInvitationDetailsVO.setTime(affiliateIncome.getPaymentTime());
            return affiliateInvitationDetailsVO;
        });
    }

    public void commissionCalculation(Integer year, Integer month) {
        if (Objects.isNull(year)) {
            year = LocalDateTime.now().getYear();
        }
        if (Objects.isNull(month)) {
            month = LocalDateTime.now().getMonthValue();
        }

        List<Map<String, Object>> monthlyAffiliateIncome = referralMapper.getMonthlyAffiliateIncome(year, month);
        // 1、总收入(近一个月通过affiliate产生的收入),未支付的金额 affiliate表中unpaid的总和
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal paidCommission = BigDecimal.ZERO;
        BigDecimal unpaidCommission = BigDecimal.ZERO;
        if (!monthlyAffiliateIncome.isEmpty()){
            Map<String, Object> monthlyIncome = monthlyAffiliateIncome.get(0);
            totalAmount = (BigDecimal) monthlyIncome.get("totalAmount");
            paidCommission = (BigDecimal) monthlyIncome.get("paidCommission");
            unpaidCommission = (BigDecimal) monthlyIncome.get("unpaidCommission");
        }

        // 2、本月新注册的Affiliate
        Map<String, Long> monthlyApprovedAffiliate = baseMapper.getMonthlyApprovedAffiliate(year, month);
        Long count = monthlyApprovedAffiliate.get("count");

        AffiliateEmailParamsDTO affiliateEmailParamsDTO = new AffiliateEmailParamsDTO();
        affiliateEmailParamsDTO.setTotalProgramRevenue(totalAmount.toString());
        affiliateEmailParamsDTO.setNewApprovedAffiliates(count.toString());
        affiliateEmailParamsDTO.setUnpaidEarnings(String.valueOf(unpaidCommission));
        affiliateEmailParamsDTO.setPaidEarnings(String.valueOf(paidCommission));

        String merchantEmail = "kimwong@code-create.com.hk";
        String developer = "xupei3360@163.com";
        String[] receiverEmail = {/*merchantEmail,*/ developer};
        // 邮件通知
        SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary");
//        emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary");
    }

    @Override
    public Affiliate getByAccountId(Long accountId) {
        QueryWrapper<Affiliate> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_id", accountId).orderByDesc("id").last("limit 1");

        return baseMapper.selectOne(queryWrapper);
    }

    /* 合代码重复了
    public void calcCouponsCommission(){
        // id存redis
        String lastTime = redisUtil.getFromString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME);
        String currentTime = LocalDateTime.now().toString();
        // 1、查上次更新之后有无使用了优惠券的新订单
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        if (!StringUtil.isNullOrEmpty(lastTime)){
            queryWrapper.gt("create_time", lastTime)
                    .lt("create_time", currentTime)
                    .isNotNull("promotion_code");
        }
        List<PaymentInfo> paymentInfos = paymentInfoService.getBaseMapper().selectList(queryWrapper);

        // key:推广码, value:用户支付的金额
        HashMap<String, Float> codeAmount = new HashMap<>();
        if (!paymentInfos.isEmpty()){
            for (PaymentInfo paymentInfo : paymentInfos){
                String promotionCode = paymentInfo.getPromotionCode();
                Float sum = codeAmount.get(promotionCode);
                if (sum == null || sum == 0.0f){
                    codeAmount.put(promotionCode, paymentInfo.getPayerTotal());
                }else {
                    codeAmount.put(promotionCode, sum + paymentInfo.getPayerTotal());
                }
            }
            for (Map.Entry<String, Float> entry : codeAmount.entrySet()){
                String promotionCode = entry.getKey();
                ProductCoupons productCoupons = stripeService.getProductCoupon(promotionCode, null);
                if (!Objects.isNull(productCoupons)){
                    // 2、计算支付金额的总和，更新totalEarnings，commission，unpaidCommission
                    float sum = productCoupons.getTotalEarnings() + entry.getValue();
                    productCoupons.setTotalEarnings(sum);
                    float commission = sum * productCoupons.getCommissionRate() / 100;
                    productCoupons.setCommission(commission);
                    productCoupons.setUnpaidCommission(commission - productCoupons.getPaidCommission());
                    productCouponsMapper.updateById(productCoupons);
                }
            }
        }
        redisUtil.addToString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME, currentTime);
    }*/

    @Override
    public List<Map<String, Object>> getAllAffiliateUsername(){
        return baseMapper.selectAllAffiliateUsername();
    }

    /*public void calcCouponsCommission() {
        String lastTime = redisUtil.getFromString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME);
        log.info("优惠券佣金计算，上次执行时间：{}", lastTime);
        String currentTime = LocalDateTime.now().toString();

        // 1. 查询新增的优惠券订单
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trade_state", "paid")
                .lt("create_time", currentTime)
                .isNotNull("promotion_code");
        Optional.ofNullable(lastTime)
                .filter(time -> !time.isEmpty())
                .ifPresent(time -> queryWrapper.gt("create_time", time));

        List<PaymentInfo> paymentInfos = paymentInfoService.list(queryWrapper);
        log.info("目前，新增使用优惠券的订单数：{}", paymentInfos.size());

        // 2. 按推广码汇总支付金额
        Map<String, BigDecimal> codeAmount = paymentInfos.stream()
                .collect(Collectors.toMap(
                        PaymentInfo::getPromotionCode,
                        payment -> new BigDecimal(payment.getPayerTotal()),
                        BigDecimal::add
                ));

        // 3. 更新佣金数据
        codeAmount.forEach((promotionCode, amount) -> {
            ProductCoupons coupon = stripeService.getProductCoupon(promotionCode, null);
            if (coupon != null) {
                updateCouponCommission(coupon, amount);
                productCouponsMapper.updateById(coupon);
            }
        });

        // 4. 更新最后执行时间
        redisUtil.addToString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME, currentTime);
    }*/

    public void calcCouponsCommission() {
        // 1. 获取并格式化时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String lastTime = redisUtil.getFromString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME);
        log.info("优惠券佣金计算，上次执行时间：{}", lastTime);

        // 2. 查询新增订单（使用>=和<）
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trade_state", "paid")
                .isNotNull("promotion_code");

        if (!StringUtils.isNullOrEmpty(lastTime)) {
            queryWrapper.ge("create_time", lastTime);  // 关键修复：>=代替>
        }
        queryWrapper.lt("create_time", LocalDateTime.now().format(formatter));

        List<PaymentInfo> paymentInfos = paymentInfoService.list(queryWrapper);
        log.info("扫描时间范围: {} - {}, 新增订单数: {}",
                lastTime, LocalDateTime.now().format(formatter), paymentInfos.size());

        // 3. 按推广码汇总支付金额
        Map<String, BigDecimal> codeAmount = paymentInfos.stream()
                .collect(Collectors.toMap(
                        PaymentInfo::getPromotionCode,
                        payment -> new BigDecimal(payment.getPayerTotal()),
                        BigDecimal::add
                ));

        // 4. 更新佣金数据
        codeAmount.forEach((promotionCode, amount) -> {
            ProductCoupons coupon = stripeService.getProductCoupon(promotionCode, null);
            if (coupon != null) {
                updateCouponCommission(coupon, amount);
                productCouponsMapper.updateById(coupon);
            }
        });

        // 5. 结束时更新Redis时间
        String newLastTime = LocalDateTime.now().format(formatter);
        redisUtil.addToString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME, newLastTime);
    }

    /**
     * 更新优惠券的佣金数据
     */
    private void updateCouponCommission(ProductCoupons coupon, BigDecimal newAmount) {
        // 总收益 = 原收益（默认0） + 新增金额
        BigDecimal totalEarnings = Optional.ofNullable(coupon.getTotalEarnings())
                .orElse(BigDecimal.ZERO)
                .add(newAmount);
        coupon.setTotalEarnings(totalEarnings);

        // 佣金 = 总收益 × 佣金比例（需除以100）
        BigDecimal commission = totalEarnings.multiply(
                BigDecimal.valueOf(coupon.getCommissionRate())
                        .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        coupon.setCommission(commission);

        // 未支付佣金 = 总佣金 - 已支付佣金（默认0）
        BigDecimal unpaidCommission = commission.subtract(
                Optional.ofNullable(coupon.getPaidCommission())
                        .orElse(BigDecimal.ZERO));
        coupon.setUnpaidCommission(unpaidCommission);
    }

}
