package com.ruoyi.system.task;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.ss.changeBalance.domain.ChangeBalanceQuery;
import com.ruoyi.ss.changeBalance.service.IChangeBalanceService;
import com.ruoyi.ss.channel.domain.ChannelQuery;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.channel.service.IChannelService;
import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO;
import com.ruoyi.ss.channelWithdraw.service.ChannelWithdrawService;
import com.ruoyi.ss.dividendDetail.domain.DividendDetailQuery;
import com.ruoyi.ss.dividendDetail.service.IDividendDetailService;
import com.ruoyi.ss.order.domain.OrderQuery;
import com.ruoyi.ss.order.service.IOrderService;
import com.ruoyi.ss.payBill.domain.PayBillQuery;
import com.ruoyi.ss.payBill.domain.enums.PayBillStatus;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.reconciliation.domain.Reconciliation;
import com.ruoyi.ss.reconciliation.domain.enums.ReconciliationDateChannelType;
import com.ruoyi.ss.reconciliation.service.IReconciliationService;
import com.ruoyi.ss.refund.domain.RefundQuery;
import com.ruoyi.ss.refund.service.IRefundService;
import com.ruoyi.ss.user.service.IUserService;
import com.ruoyi.ss.withdraw.domain.WithdrawQuery;
import com.ruoyi.ss.withdraw.service.IWithdrawService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

import static com.ruoyi.common.constant.ServiceConstants.REFUND;

/**
 * 定时任务调度测试
 *
 * @author ruoyi
 */
@Slf4j
@Component("reconciliationTask")
public class ReconciliationTask {

    @Autowired
    private IReconciliationService reconciliationService;

    @Autowired
    private IChannelService channelService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IRefundService refundService;

    @Resource
    private IDividendDetailService dividendDetailService;

    @Autowired
    private ChannelWithdrawService channelWithdrawService;

    @Autowired
    private PayBillService paymentService;

    @Autowired
    private IChangeBalanceService changeBalanceService;

    @Autowired
    private IWithdrawService withdrawService;

    @Autowired
    private IUserService userService;


    /**
     *  平台对账
     */
    public void reconciliation(String startDateStr, String endDateStr) {
        log.info("-------------------【定时任务】平台对账---开始----------------");

        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 将传入的字符串日期转换为 LocalDate 对象
        LocalDate startDate = LocalDate.parse(startDateStr, formatter);
        LocalDate endDate = LocalDate.parse(endDateStr, formatter);

        // 获取渠道列表
        ChannelQuery query = new ChannelQuery();
        query.setEnabled(true);
        List<ChannelVO> channels = channelService.selectSmChannelList(query);
        List<ChannelWithdrawVO> channelWithdraws = channelWithdrawService.selectAllChannelWithdrawList();

        // 遍历每一天
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            // 统计支付渠道对账
            LocalDate finalDate = date;
            channels.forEach(channel -> {
                Reconciliation rec = getReconciliation(ReconciliationDateChannelType.PAYMENT, channel.getChannelId(),channel.getName(), finalDate);

                int i = reconciliationService.insertSsReconciliation(rec);
                log.info("【定时任务】保存支付渠道对账---{}", i > 0 ? "成功" : "失败");
                /* 保存对账*/
            });

            // 统计提现渠道对账
            channelWithdraws.forEach(channel -> {
                Reconciliation rec = getReconciliation(ReconciliationDateChannelType.WITHDRAW, channel.getChannelId(),channel.getName(), finalDate);

                int i = reconciliationService.insertSsReconciliation(rec);
                log.info("【定时任务】保存提现渠道对账---{}", i > 0 ? "成功" : "失败");
                /* 保存对账*/
            });
        }

        log.info("-------------------【定时任务】平台对账---结束----------------");
    }

    private @NotNull Reconciliation getReconciliation(ReconciliationDateChannelType channelType,Long channelId, String channelName, LocalDate date) {
        /* 统计对账 */
        Reconciliation rec = new Reconciliation();
        rec.setChannel(channelId);
        rec.setChannelName(channelName);
        rec.setDay(DateUtils.getYYYY_MM_DD(date));
        if(ReconciliationDateChannelType.PAYMENT.equals(channelType)){
            OrderQuery orderQuery = new OrderQuery();
            orderQuery.setPayChannel(channelId);
            orderQuery.setPayStartTime(date);
            orderQuery.setPayEndTime(date);
            BigDecimal orderFee = orderService.getOrderFee(orderQuery);
            rec.setOrderPaid(orderFee);

            RefundQuery ref = new RefundQuery();
            ref.setStartTime(date);
            ref.setEndTime(date);
            BigDecimal refundedAmount = refundService.getRefundedAmount(ref);
            rec.setOrderRefund(refundedAmount);
            rec.setSettlementAmount(orderFee.subtract(refundedAmount));

            // 用户分成
            DividendDetailQuery div = new DividendDetailQuery();
            div.setPayChannel(channelId);
            div.setStartTime(date);
            div.setEndTime(date);
            BigDecimal income = dividendDetailService.getIncome(div);
            rec.setUserDivide(income);

            // 用户退款
            ChangeBalanceQuery query1 = new ChangeBalanceQuery();
            query1.setBusType(REFUND);
            query1.setCreateTime(DateUtils.toDate(date));
            BigDecimal bigDecimal = changeBalanceService.selectFee(query1);
            rec.setUserRefund(bigDecimal);

            //用户结算
            rec.setUserSettlement(income.subtract(bigDecimal));
            rec.setType(ReconciliationDateChannelType.PAYMENT.getCode());
            rec.setUserBalance(userService.selectAllBalance());


            //平台服务费
            BigDecimal platformServiceFee = orderService.getPlatformServiceFee(orderQuery);
            rec.setPlatformServiceFee(platformServiceFee);

            //渠道成本
            PayBillQuery payQuery = new PayBillQuery();
            payQuery.setPayDate(date);
            payQuery.setStatusList(PayBillStatus.payedList());
            payQuery.setChannelId(channelId);
            rec.setChannelCost(paymentService.selectSumOfChannelCost(payQuery));
            //订单数
            rec.setOrderCount(orderService.getCount(orderQuery));

        }else{
            //用户提现
            WithdrawQuery withdrawQuery = new WithdrawQuery();
            withdrawQuery.setWithdrawChannelId(channelId);
            withdrawQuery.setStatusList(Arrays.asList("1", "4"));
            withdrawQuery.setStartData(date);
            // 日期
            BigDecimal userWithdrawAmount = withdrawService.selectWithdrawAmount(withdrawQuery);
            rec.setUserWithdrawAmount(userWithdrawAmount);
            //提现服务费
            BigDecimal bigDecimal = withdrawService.selectHandlingCharge(withdrawQuery);
            rec.setWithdrawServiceFee(bigDecimal);
            rec.setType(ReconciliationDateChannelType.WITHDRAW.getCode());
        }
        BigDecimal add = MathUtils.addDecimal(rec.getPlatformServiceFee(), rec.getWithdrawServiceFee());
        rec.setPlatformRevenue(MathUtils.subtractDecimal(add,rec.getChannelCost()));

        return rec;
    }
}
