package com.starry.admin.common.task;

import com.starry.admin.modules.clerk.module.entity.PlayClerkRankingInfoEntity;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkRankingInfoService;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
import com.starry.admin.modules.system.module.entity.SysTenantEntity;
import com.starry.admin.modules.system.service.ISysTenantService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.utils.IdUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 订单排名结算信息
 *
 * @author admin
 * @since 2024/5/28 下午2:42
 **/
@Component
public class OrderRankingSettlementTask {

    @Resource
    ISysTenantService sysTenantService;

    @Resource
    private IPlayClerkUserInfoService clerkUserInfoService;

    @Resource
    private IPlayOrderInfoService orderInfoService;

    @Resource
    private IPlayClerkRankingInfoService clerkRankingInfoService;

    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 当日订单结算，查询前一日的订单信息，生成订单排名数据 每天凌晨0点5分0秒时触发执行
     */
    @Scheduled(cron = "0 5 0 * * ?")
    public void dailyRanking() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String startTime = LocalDate.now().minusDays(1).atStartOfDay().format(df);
        String endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX).format(df);
        rankingSettlement(startTime, endTime, "0");
    }

    /**
     * 每周订单结算，周一凌晨30分执行，查询上一周的订单，然后生成订单排行数据 每周一凌晨0点30分0秒时触发执行
     */
    @Scheduled(cron = "0 30 0 ? * MON")
    public void weeklyRankingSettlement() {

        String startTime = LocalDate.now().minusDays(8).atStartOfDay().format(df);
        String endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX).format(df);
        rankingSettlement(startTime, endTime, "1");
    }

    /**
     * 生产排行信息 1、查询所有的租户信息 2、查询每个租户的用户，以及他们在对应时间段的订单 3、根据订单生产排行信息
     *
     * @param startTime     接单开始时间
     * @param endTime       接单截至时间
     * @param weeklyRanking weeklyRanking 日排名还是周排名（0:每日排名;1:每周排名）
     * @author admin
     * @since 2024/6/12 15:21
     **/
    public void rankingSettlement(String startTime, String endTime, String weeklyRanking) {
        // 1、查询所有的租户信息
        List<SysTenantEntity> tenantEntities = sysTenantService.listAll();
        // 2、查询每个租户的用户，以及他们的订单信息
        for (SysTenantEntity tenantEntity : tenantEntities) {
            SecurityUtils.setTenantId(tenantEntity.getTenantId());
            // 当前租户用户列表
            List<PlayClerkUserInfoEntity> clerkUserReturnVos = clerkUserInfoService.listAll();
            List<PlayClerkRankingInfoEntity> clerkRankingInfoEntities = new ArrayList<>();
            // 查询当前租户、当前排行、的最后一次统计编号
            Integer newSerialNumber = clerkRankingInfoService.selectSerialNumber(weeklyRanking);
            // 生成每个人的订单排行信息
            for (PlayClerkUserInfoEntity clerkUserInfo : clerkUserReturnVos) {
                // 生成订单排行数据
                PlayClerkRankingInfoEntity clerkRanking = getClerkRanking(clerkUserInfo.getId(), startTime, endTime, weeklyRanking, newSerialNumber);
                clerkRanking.setTenantId(tenantEntity.getTenantId());
                clerkRankingInfoEntities.add(clerkRanking);
            }
            // 更新排行名次
            clerkRankingInfoEntities.sort((p1, p2) -> p2.getOrderNumber() - p1.getOrderNumber());
            for (int i = 0; i < clerkRankingInfoEntities.size(); i++) {
                PlayClerkRankingInfoEntity item = clerkRankingInfoEntities.get(i);
                item.setRankingIndex(i + 1);
                if (i > 0) {
                    item.setPreviousMoney(clerkRankingInfoEntities.get(i - 1).getOrderMoney().subtract(item.getOrderMoney()));
                }
            }
            // 排名数据生成后，将以往排名状态标记为历史排名
            clerkRankingInfoService.updateClerkRankingInfo(weeklyRanking, newSerialNumber);
            // 插入本次排名数据
            clerkRankingInfoService.saveBatch(clerkRankingInfoEntities);
        }
    }

    /**
     * 生产当前排行信息
     *
     * @param clerkId       店员ID
     * @param startTime     排行开始统计日期 yyyy-mm-dd 00:00:00
     * @param endTime       排行结束统计日期 yyyy-mm-dd 23:59:59
     * @param weeklyRanking 日排名还是周排名（0:每日排名;1:每周排名）
     * @param serialNumber  查询当前租户、当前排行、的最后一次统计编号
     * @author admin
     * @since 2024/6/7 11:43
     **/
    public PlayClerkRankingInfoEntity getClerkRanking(String clerkId, String startTime, String endTime, String weeklyRanking, Integer serialNumber) {
        List<PlayOrderInfoEntity> orderInfoEntities = orderInfoService.listByTime(clerkId, startTime, endTime, null);
        int orderNumber = orderInfoEntities.size();
        BigDecimal orderMoney = BigDecimal.ZERO;
        Integer orderContinueNumber = 0;
        BigDecimal orderContinueMoney = BigDecimal.ZERO;
        int ordersExpiredNumber = 0;
        Set<String> customIds = new HashSet<>();
        for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) {
            customIds.add(orderInfoEntity.getAcceptBy());
            orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney());
            if ("0".equals(orderInfoEntity.getFirstOrder())) {
                orderContinueNumber++;
                orderContinueMoney = orderContinueMoney.add(orderInfoEntity.getOrderMoney());
            }
            if ("1".equals(orderInfoEntity.getOrdersExpiredState())) {
                ordersExpiredNumber++;
            }
        }
        BigDecimal orderContinueProportion = orderNumber == 0 ? BigDecimal.ZERO : new BigDecimal(ordersExpiredNumber).divide(new BigDecimal(orderNumber), 4, RoundingMode.HALF_UP).add(new BigDecimal(100));
        BigDecimal averageUnitPrice = customIds.isEmpty() ? BigDecimal.ZERO : orderMoney.divide(new BigDecimal(customIds.size()), 4, RoundingMode.HALF_UP);
        PlayClerkRankingInfoEntity rankingInfo = new PlayClerkRankingInfoEntity();
        rankingInfo.setId(IdUtils.getUuid());
        rankingInfo.setClerkId(clerkId);
        // 默认为当前统计
        rankingInfo.setHistoricalStatistics("0");
        rankingInfo.setWeeklyRanking(weeklyRanking);
        // 当前统计编号+1
        rankingInfo.setSerialNumber(serialNumber + 1);
        // 每个人的名次默认为1，后面在进行排序更新名次
        rankingInfo.setRankingIndex(1);
        // 统计时间
        rankingInfo.setStartCountDate(LocalDate.parse(startTime, df));
        rankingInfo.setEndCountDate(LocalDate.parse(endTime, df));
        rankingInfo.setOrderNumber(orderInfoEntities.size());
        rankingInfo.setOrderMoney(orderMoney);
        rankingInfo.setOrderContinueMoney(orderContinueMoney);
        rankingInfo.setOrderContinueNumber(orderContinueNumber);
        rankingInfo.setOrderContinueProportion(orderContinueProportion);
        rankingInfo.setOrdersExpiredNumber(ordersExpiredNumber);
        rankingInfo.setCustomNumber(customIds.size());
        rankingInfo.setAverageUnitPrice(averageUnitPrice);
        rankingInfo.setPreviousMoney(BigDecimal.ZERO);
        rankingInfo.setSettlementDate(LocalDate.now());
        return rankingInfo;
    }

}
