package org.jeecg.modules.quartz.job;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.modules.pay.config.WeChatProfitSharingService;
import org.jeecg.modules.system.app.entity.AppOrder;
import org.jeecg.modules.system.app.mapper.AppOrderMapper;
import org.jeecg.modules.system.app.service.IAppOrderService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

import static java.lang.Thread.sleep;

/**
 * @Description 分账定时任务(包场和无固定场)
 */
@Slf4j
@AllArgsConstructor
@Component
public class ProfitSharingJonService {

    private final WeChatProfitSharingService weChatProfitSharingService;
    private final AppOrderMapper appOrderMapper;


    /**
     * 每日2点执行
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void profitSharingExecute() {
        log.info("开始执行分账定时任务");
        try {
            //包场和无固定场
            List<AppOrder> appOrders = appOrderMapper.selectList(Wrappers.lambdaQuery(AppOrder.class)
                    .eq(AppOrder::getPayStatus, CommonConstant.NUMBER_1)
                    .in(AppOrder::getOrderType, CommonConstant.ORDER_TYPE_1, CommonConstant.ORDER_TYPE_2)
            );
            for (AppOrder appOrder : appOrders) {
                //判断当前订单是否到期，是否进行分账
                Date date = appOrder.getCreateTime();
                // 将Date转换为Instant时间戳
                Instant instant = date.toInstant();
                // 结合系统默认时区生成ZonedDateTime
                ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
                // 提取日期部分
                LocalDate localDate = zonedDateTime.toLocalDate();
                //校验时间
                boolean validRange = isValidRange(localDate, 5);
                if (validRange) {
                    //分账
                    JSONObject jsonObject = weChatProfitSharingService.profitSharing(appOrder.getOrderCode());
                    log.info("订单：{}================分账结果：{}",appOrder.getOrderCode(),jsonObject);
                }
            }
        } catch (Exception e) {
            log.error("分账定时任务异常", e);
        }
    }

    /**
     * 每日23点执行
     */
    @Scheduled(cron = "0 0 23 * * ?")
    public void getProfitSharingResultExecute() {
        log.info("开始执行分账结果查询定时任务");
        try {
            List<AppOrder> appOrders = appOrderMapper.selectList(Wrappers.lambdaQuery(AppOrder.class)
                    .eq(AppOrder::getProfitSharingStatus, CommonConstant.NUMBER_1)
            );
            for (AppOrder appOrder : appOrders) {
                sleep(1000);
                //查询分账结果
                JSONObject profitSharingResult = weChatProfitSharingService.getProfitSharingResult(appOrder.getOrderCode());
                log.info("订单：{}================分账结果：{}",appOrder.getOrderCode(),profitSharingResult);
            }
        } catch (Exception e) {
            log.error("分账结果查询定时任务异常", e);
        }
    }

    /**
     * 验证当前时间是否满足：
     * 1. 当前时间早于目标日期的30天后
     * 2. 当前时间与目标日期的30天后间隔不超过N天
     *
     * @param targetDate 目标日期（null会抛出异常）
     * @return 满足条件返回true，否则返回false
     * @throws IllegalArgumentException 当输入日期为null时抛出
     */
    public static boolean isValidRange(LocalDate targetDate, int days) {
        if (targetDate == null) {
            throw new IllegalArgumentException("目标日期不能为null");
        }

        // 获取当前日期（带时区信息）
        LocalDate currentDate = LocalDate.now();

        // 计算目标日期的30天后日期
        LocalDate deadlineDate = targetDate.plusDays(30);

        // 验证当前时间必须早于30天后的日期
        if (currentDate.isAfter(deadlineDate)) {
            return false;
        }

        // 计算日期间隔（精确到天）
        long daysBetween = ChronoUnit.DAYS.between(currentDate, deadlineDate);

        // 验证间隔是否在N天内
        return daysBetween <= days;
    }
}
