package com.gxwebsoft.shop.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.glt.service.GltTicketRevokeService;
import com.gxwebsoft.shop.entity.ShopOrder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 历史订单修复：对已退款订单补偿撤销水票相关数据。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ShopOrderGltRepairService {

    /** shop_order.order_status：退款成功 */
    private static final int ORDER_STATUS_REFUND_SUCCESS = 6;

    private final ShopOrderService shopOrderService;
    private final GltTicketRevokeService gltTicketRevokeService;

    public RepairResult revokeTicketsForRefundedOrders(Integer tenantId,
                                                       List<Integer> orderIds,
                                                       List<String> orderNos,
                                                       LocalDateTime refundTimeStart,
                                                       LocalDateTime refundTimeEnd,
                                                       Integer batchSize,
                                                       boolean dryRun) {
        if (tenantId == null) {
            throw new IllegalArgumentException("tenantId不能为空");
        }

        int limit = batchSize == null ? 200 : Math.max(1, Math.min(batchSize, 2000));
        List<ShopOrder> orders = new ArrayList<>();

        // 1) 精准修复：指定 orderIds / orderNos
        if (orderIds != null && !orderIds.isEmpty()) {
            orders = shopOrderService.list(new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getTenantId, tenantId)
                .eq(ShopOrder::getDeleted, 0)
                .eq(ShopOrder::getOrderStatus, ORDER_STATUS_REFUND_SUCCESS)
                .in(ShopOrder::getOrderId, orderIds)
                .last("limit " + limit));
        } else if (orderNos != null && !orderNos.isEmpty()) {
            orders = shopOrderService.list(new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getTenantId, tenantId)
                .eq(ShopOrder::getDeleted, 0)
                .eq(ShopOrder::getOrderStatus, ORDER_STATUS_REFUND_SUCCESS)
                .in(ShopOrder::getOrderNo, orderNos)
                .last("limit " + limit));
        } else {
            // 2) 扫描修复：按 refundTime 窗口分页处理
            LambdaQueryWrapper<ShopOrder> qw = new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getTenantId, tenantId)
                .eq(ShopOrder::getDeleted, 0)
                .eq(ShopOrder::getOrderStatus, ORDER_STATUS_REFUND_SUCCESS);
            if (refundTimeStart != null) {
                qw.ge(ShopOrder::getRefundTime, refundTimeStart);
            }
            if (refundTimeEnd != null) {
                qw.le(ShopOrder::getRefundTime, refundTimeEnd);
            }
            orders = shopOrderService.list(qw.orderByAsc(ShopOrder::getRefundTime).orderByAsc(ShopOrder::getOrderId).last("limit " + limit));
        }

        int scanned = orders == null ? 0 : orders.size();
        int revokedTickets = 0;
        int revokedOrders = 0;
        List<Integer> processedOrderIds = new ArrayList<>();

        if (orders != null) {
            for (ShopOrder o : orders) {
                if (o == null || o.getOrderId() == null) {
                    continue;
                }
                processedOrderIds.add(o.getOrderId());
                if (dryRun) {
                    continue;
                }
                int revoked = gltTicketRevokeService.revokeByShopOrder(
                    tenantId,
                    o.getOrderId(),
                    o.getOrderNo(),
                    "历史退款订单补偿撤销水票"
                );
                if (revoked > 0) {
                    revokedTickets += revoked;
                    revokedOrders++;
                }
            }
        }

        return new RepairResult(scanned, revokedOrders, revokedTickets, processedOrderIds, dryRun);
    }

    public record RepairResult(int scannedOrders,
                               int ordersWithTicketsRevoked,
                               int revokedTicketCount,
                               List<Integer> processedOrderIds,
                               boolean dryRun) {
    }
}

