package com.yc.ship.module.trade.service.order.impl;

import com.alibaba.ttl.threadpool.TtlExecutors;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailBaseDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
import com.yc.ship.module.trade.dal.mysql.order.TradeDetailBaseMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeDetailMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeOrderMapper;
import com.yc.ship.module.trade.enums.TradeOrderTravelEnum;
import com.yc.ship.module.trade.enums.VoucherStatusEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 获取订单出行状态
 */
@Slf4j
@Service
@Validated
@RequiredArgsConstructor
public class TradeOrderTravelService {

    private final TradeOrderMapper tradeOrderMapper;
    private final TradeDetailMapper tradeDetailMapper;
    private final TradeDetailBaseMapper tradeDetailBaseMapper;
    // 线程池通过构造函数初始化
    private final ExecutorService executor = initThreadPool();
    // 批次大小
    private static final int BATCH_SIZE = 100;

    /**
     * 初始化线程池
     */
    private ExecutorService initThreadPool() {
        // 配置线程池参数
        int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
        int maxPoolSize = corePoolSize * 2;
        long keepAliveTime = 60L;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(1000);

        // 创建线程池（使用阿里TransmittableThreadLocal包装）
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        return TtlExecutors.getTtlExecutorService(threadPoolExecutor);
    }

    @TenantIgnore
    public void updateOrderTravelStatus(Long orderId) {
        TradeOrderDO orderDO = tradeOrderMapper.selectById(orderId);
        if (orderDO == null || orderDO.getOrderStatus() < 6) {
            return;
        }
        Integer oldTravelStatus = orderDO.getTravelStatus();
        List<TradeDetailDO> detailList = tradeDetailMapper.selectList(TradeDetailDO::getOrderId, orderId);
        if (detailList == null || detailList.isEmpty()) {
            return;
        }
        List<TradeDetailDO> refundedList = detailList.stream().filter(detail ->
                Objects.equals(VoucherStatusEnum.REFUND.getStatus(), detail.getVoucherStatus())).collect(Collectors.toList());
        if (refundedList.size() == detailList.size()) {
            // 已取消：全是退款
            if (!Objects.equals(TradeOrderTravelEnum.Cancelled.getStatus(), oldTravelStatus)) {
                tradeOrderMapper.update(new LambdaUpdateWrapper<TradeOrderDO>()
                        .set(TradeOrderDO::getTravelStatus, TradeOrderTravelEnum.Cancelled.getStatus())
                        .eq(TradeOrderDO::getId, orderId)
                );
            }
            return;
        }
        if (!refundedList.isEmpty()) {
            detailList.removeAll(refundedList);
        }
        // 9部分退款 转化状态
        List<TradeDetailDO> partRefundedList = detailList.stream().filter(detail ->
                Objects.equals(VoucherStatusEnum.PART_REFUND.getStatus(), detail.getVoucherStatus())).collect(Collectors.toList());
        partRefundedList.forEach(item -> {
            List<TradeDetailBaseDO> detailBaseList = tradeDetailBaseMapper.selectList(TradeDetailBaseDO::getDetailId, item.getId());
            int checkedNum = detailBaseList.stream().mapToInt(TradeDetailBaseDO::getUseStatus).sum();
            // 子票有核销，该票等于8部分核销 没有则等于1待使用
            item.setVoucherStatus(checkedNum == 0 ? VoucherStatusEnum.UNUSED.getStatus() : VoucherStatusEnum.PART_VERIFIED.getStatus());
        });

        int travelStatus;
        List<TradeDetailDO> unsedList = detailList.stream().filter(detail -> VoucherStatusEnum.isUnused(detail.getVoucherStatus())).collect(Collectors.toList());
        List<TradeDetailDO> checkedList = detailList.stream().filter(detail -> VoucherStatusEnum.isChecked(detail.getVoucherStatus())).collect(Collectors.toList());
        if (unsedList.size() == detailList.size()) {
            // 未出行：全是未使用
            travelStatus = TradeOrderTravelEnum.Not_Traveled.getStatus();
        } else if (checkedList.size() == detailList.size()) {
            // 已结束：全是核销
            travelStatus = TradeOrderTravelEnum.Finished.getStatus();
        } else if (!unsedList.isEmpty()) {
            // 部分出行：未使用A状态的数量>0
            travelStatus = TradeOrderTravelEnum.Part_Traveled.getStatus();
        } else {
            // 已出行：只含有核销
            travelStatus = TradeOrderTravelEnum.Traveled.getStatus();
        }
        if (!Objects.equals(travelStatus, oldTravelStatus)) {
            tradeOrderMapper.update(new LambdaUpdateWrapper<TradeOrderDO>()
                    .eq(TradeOrderDO::getId, orderId).set(TradeOrderDO::getTravelStatus, travelStatus));
        }
    }

    @TenantIgnore
    public void updateOrderTravelStatus(TradeOrderDO orderDO) {
        if (orderDO == null || orderDO.getOrderStatus() < 6) {
            return;
        }
        Long orderId = orderDO.getId();
        Integer oldTravelStatus = orderDO.getTravelStatus();
        List<TradeDetailDO> detailList = tradeDetailMapper.selectList(TradeDetailDO::getOrderId, orderId);
        if (detailList == null || detailList.isEmpty()) {
            return;
        }
        List<TradeDetailDO> refundedList = detailList.stream().filter(detail ->
                Objects.equals(VoucherStatusEnum.REFUND.getStatus(), detail.getVoucherStatus())).collect(Collectors.toList());
        if (refundedList.size() == detailList.size()) {
            // 已取消：全是退款
            if (!Objects.equals(TradeOrderTravelEnum.Cancelled.getStatus(), oldTravelStatus)) {
                tradeOrderMapper.update(new LambdaUpdateWrapper<TradeOrderDO>()
                        .set(TradeOrderDO::getTravelStatus, TradeOrderTravelEnum.Cancelled.getStatus())
                        .eq(TradeOrderDO::getId, orderId)
                );
            }
            return;
        }
        if (!refundedList.isEmpty()) {
            detailList.removeAll(refundedList);
        }
        // 9部分退款 转化状态
        List<TradeDetailDO> partRefundedList = detailList.stream().filter(detail ->
                Objects.equals(VoucherStatusEnum.PART_REFUND.getStatus(), detail.getVoucherStatus())).collect(Collectors.toList());
        partRefundedList.forEach(item -> {
            List<TradeDetailBaseDO> detailBaseList = tradeDetailBaseMapper.selectList(TradeDetailBaseDO::getDetailId, item.getId());
            int checkedNum = detailBaseList.stream().mapToInt(TradeDetailBaseDO::getUseStatus).sum();
            // 子票有核销，该票等于8部分核销 没有则等于1待使用
            item.setVoucherStatus(checkedNum == 0 ? VoucherStatusEnum.UNUSED.getStatus() : VoucherStatusEnum.PART_VERIFIED.getStatus());
        });

        int travelStatus;
        List<TradeDetailDO> unsedList = detailList.stream().filter(detail -> VoucherStatusEnum.isUnused(detail.getVoucherStatus())).collect(Collectors.toList());
        List<TradeDetailDO> checkedList = detailList.stream().filter(detail -> VoucherStatusEnum.isChecked(detail.getVoucherStatus())).collect(Collectors.toList());
        if (unsedList.size() == detailList.size()) {
            // 未出行：全是未使用
            travelStatus = TradeOrderTravelEnum.Not_Traveled.getStatus();
        } else if (checkedList.size() == detailList.size()) {
            // 已结束：全是核销
            travelStatus = TradeOrderTravelEnum.Finished.getStatus();
        } else if (!unsedList.isEmpty()) {
            // 部分出行：未使用A状态的数量>0
            travelStatus = TradeOrderTravelEnum.Part_Traveled.getStatus();
        } else {
            // 已出行：只含有核销
            travelStatus = TradeOrderTravelEnum.Traveled.getStatus();
        }
        if (!Objects.equals(travelStatus, oldTravelStatus)) {
            log.error("更新出行状态"+orderDO.getOrderNo()+"状态"+travelStatus);
            tradeOrderMapper.update(new LambdaUpdateWrapper<TradeOrderDO>()
                    .eq(TradeOrderDO::getId, orderId).set(TradeOrderDO::getTravelStatus, travelStatus));
        }
    }

    /**
     * 初始化未设置出行状态的订单
     * 耗时非常长，最好不执行
     * @return 结果
     */
    public String initOrderTravelStatus() {
        long millis = System.currentTimeMillis();
        Integer totalCount = tradeOrderMapper.queryTravelStatusIsNullTotal();
        if (totalCount == null || totalCount == 0) {
            return "未查询到需设置出行状态的订单";
        }

        // 计算总页数
        int totalPages = (totalCount + BATCH_SIZE - 1) / BATCH_SIZE;
        // 创建CountDownLatch用于等待所有任务完成
        CountDownLatch latch = new CountDownLatch(totalPages);
        // 提交分页任务到线程池
        for (int page = 1; page <= totalPages; page++) {
            final int currentPage = page;
            executor.submit(() -> {
                try {
                    // 查询当前页的订单ID列表
                    List<Long> orderIds = tradeOrderMapper.queryTravelStatusIsNull((currentPage - 1), BATCH_SIZE);

                    for (Long orderId : orderIds) {
                        // 批量更新订单状态
                        updateOrderTravelStatus(orderId);
                    }
                    System.out.printf("线程[%s] 完成第%d页订单状态更新, 共%d条%n",
                            Thread.currentThread().getName(), currentPage, orderIds.size());
                } catch (Exception e) {
                    System.err.printf("线程[%s] 处理第%d页订单时发生异常: %s%n",
                            Thread.currentThread().getName(), currentPage, e.getMessage());
                    // 这里可以添加重试逻辑或记录错误订单
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有任务完成
        try {
            latch.await();
            System.out.println("所有订单状态更新任务已完成");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("等待任务完成时被中断: " + e.getMessage());
        }

        return "订单数：" + totalCount + " 用时：" + (System.currentTimeMillis() - millis) + "毫秒";
    }

}
