package com.ai.da.service.impl;

import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.mapper.primary.ReferralMapper;
import com.ai.da.mapper.primary.entity.Affiliate;
import com.ai.da.mapper.primary.entity.Referral;
import com.ai.da.model.dto.EditReferralDTO;
import com.ai.da.model.dto.ReferralPageQueryDTO;
import com.ai.da.model.vo.ReferralPageQueryVO;
import com.ai.da.service.AffiliateService;
import com.ai.da.service.ReferralService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
public class ReferralServiceImpl extends ServiceImpl<ReferralMapper, Referral> implements ReferralService {

    @Resource
    private AffiliateService affiliateService;

    // Referral Recap
    // 当有用户通过链接成功订阅AiDA后。这里应该要出现一笔待支付给affiliate的记录
    // 每一笔交易需要管理员Accept才能被算为佣金（有审批这个过程）

    // 查询所有referral (分页查)
    // 允许按推广人用户名、记录产生时间、记录状态分页查询
    public IPage<ReferralPageQueryVO> queryByPage(ReferralPageQueryDTO referralPageQueryDTO) {
        // 1. 构建查询条件
        QueryWrapper<ReferralPageQueryVO> queryWrapper = new QueryWrapper<>();

        if (referralPageQueryDTO.getAffiliateId() != null && referralPageQueryDTO.getAffiliateId() != 0L) {
            queryWrapper.eq("r.affiliate_id", referralPageQueryDTO.getAffiliateId());
        }
        if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getStartTime())) {
            queryWrapper.gt("r.create_time", referralPageQueryDTO.getStartTime());
        }
        if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getEndTime())) {
            queryWrapper.lt("r.create_time", referralPageQueryDTO.getEndTime());
        }
        if (!StringUtil.isNullOrEmpty(referralPageQueryDTO.getStatus()) && !"All Types".equals(referralPageQueryDTO.getStatus())) {
            queryWrapper.eq("r.status", referralPageQueryDTO.getStatus());
        }

        queryWrapper.eq("r.is_deleted", 0);

        // 2. 执行分页查询（返回的是 ReferralVO）
        Page<ReferralPageQueryVO> page = new Page<>(referralPageQueryDTO.getPage(), referralPageQueryDTO.getSize());
        return baseMapper.selectReferralWithAffiliate(page, queryWrapper);
    }

    // 编辑referral
    @Transactional(rollbackFor = Exception.class)
    public void editReferral(EditReferralDTO editReferralDTO){
        Referral referral = baseMapper.selectById(editReferralDTO.getId());
        if (Objects.isNull(referral)){
            throw new BusinessException("unknown referral id");
        }

        if (Objects.nonNull(editReferralDTO.getCommission()) && editReferralDTO.getCommission().compareTo(referral.getCommission()) != 0){
            log.info("设置referral id为{} 原佣金 {} 设置为 {}", referral.getId(), referral.getAffiliateId(), editReferralDTO.getCommission());
            referral.setCommission(editReferralDTO.getCommission());
            referral.setUpdateTime(LocalDateTime.now());
        }
        if (!StringUtil.isNullOrEmpty(editReferralDTO.getStatus()) && !editReferralDTO.getStatus().equals(referral.getStatus())){
            // 如果该笔佣金审批通过，则自动转为未支付状态
            if (editReferralDTO.getStatus().equals("Accept")){
                editReferralDTO.setStatus("Unpaid");
            }
            log.info("设置referral id为{} 原状态 {} 设置为 {}", referral.getId(), referral.getStatus(), editReferralDTO.getStatus());
            referral.setStatus(editReferralDTO.getStatus());
            referral.setUpdateTime(LocalDateTime.now());
        }
        boolean b = updateById(referral);

        if (b){
            Affiliate affiliate = affiliateService.getBaseMapper().selectById(referral.getAffiliateId());

            // 如果修改了referral的状态，则需要同步修改affiliate已支付或未支付的金额总数
            // 在平台的总未支付
            BigDecimal unpaid = baseMapper.sumAmount(referral.getAffiliateId(), Collections.singletonList("Unpaid"), null, null);

            // 已支付和未支付的值肯定是同时发生变化
            unpaid = Objects.isNull(unpaid) ? BigDecimal.ZERO : unpaid;
            if (BigDecimal.valueOf(affiliate.getUnpaidEarnings()).compareTo(unpaid) != 0){
                LocalDateTime start = YearMonth.now().atDay(1).atStartOfDay();          // 本月第一天 00:00:00
                LocalDateTime end = YearMonth.now().atEndOfMonth().atTime(23, 59, 59);
                // 本月的总收入（包括已支付和未支付）
                BigDecimal monthlyEarning = baseMapper.sumAmount(referral.getAffiliateId(), Arrays.asList("Unpaid", "Paid"), start, end);
                // 在平台的总收入
                BigDecimal totalEarning = baseMapper.sumAmount(referral.getAffiliateId(), Arrays.asList("Unpaid", "Paid"), null, null);
                affiliate.setUnpaidEarnings(unpaid.floatValue());
                affiliate.setMonthlyEarnings(Objects.nonNull(monthlyEarning) ? monthlyEarning.floatValue() : 0);
                affiliate.setTotalEarnings(Objects.nonNull(totalEarning) ? totalEarning.floatValue() : 0);
                affiliate.setUpdateTime(LocalDateTime.now());
                affiliateService.getBaseMapper().updateById(affiliate);
            }
        }
    }

    // 批量删除
    public void deleteReferral(List<Long> idList){
        if (!idList.isEmpty()){
            baseMapper.batchDeleteByIds(idList);
        }
    }
}
