package com.gxwebsoft.shop.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.annotation.IgnoreTenant;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 订单取消服务实现
 *
 * @author WebSoft
 * @since 2025-01-26
 */
@Slf4j
@Service
public class OrderCancelServiceImpl implements OrderCancelService {
    private static final int DEDUCT_STOCK_TYPE_PAY = 20; // 付款减库存：下单不扣库存，因此未支付取消无需回退

    @Autowired
    private ShopOrderService shopOrderService;

    @Autowired
    private ShopOrderGoodsService shopOrderGoodsService;

    @Autowired
    private ShopGoodsService shopGoodsService;

    @Autowired
    private ShopGoodsSkuService shopGoodsSkuService;

    @Autowired
    private CouponStatusService couponStatusService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(ShopOrder order) {
        try {
            log.info("开始取消订单，订单号：{}，订单ID：{}", order.getOrderNo(), order.getOrderId());

            if (order.getOrderId() == null) {
                log.warn("订单ID为空，无法取消");
                return false;
            }

            // 1. 检查订单状态
            if (order.getPayStatus() != null && order.getPayStatus()) {
                log.warn("订单已支付，无法取消，订单号：{}", order.getOrderNo());
                return false;
            }

            if (order.getOrderStatus() != null && order.getOrderStatus() != 0) {
                log.warn("订单状态不是待支付，无法取消，订单号：{}，当前状态：{}", order.getOrderNo(), order.getOrderStatus());
                return false;
            }

            // 2. 更新订单状态为已取消（只更新必要字段 + 加条件，避免并发/越权导致“取消后又被改成退款中”等脏状态）
            LocalDateTime now = LocalDateTime.now();
            String reason = StrUtil.isNotBlank(order.getCancelReason())
                    ? order.getCancelReason()
                    : "系统自动取消（超时未支付）";

            boolean updateSuccess = shopOrderService.update(
                    new LambdaUpdateWrapper<ShopOrder>()
                            .eq(ShopOrder::getOrderId, order.getOrderId())
                            .eq(ShopOrder::getPayStatus, false)
                            .eq(ShopOrder::getOrderStatus, 0)
                            .set(ShopOrder::getOrderStatus, 2) // 2表示已取消
                            .set(ShopOrder::getCancelTime, now)
                            .set(ShopOrder::getCancelReason, reason)
            );
            if (!updateSuccess) {
                log.error("更新订单状态失败（可能已被支付/退款/取消），订单号：{}，订单ID：{}", order.getOrderNo(), order.getOrderId());
                return false;
            }

            // 让后续库存/优惠券逻辑使用最新状态（不再依赖 updateById 回写）
            order.setOrderStatus(2);
            order.setCancelTime(now);
            order.setCancelReason(reason);

            // 3. 回退库存
            boolean stockRestored = restoreOrderStock(order);
            if (!stockRestored) {
                log.error("回退库存失败，订单号：{}", order.getOrderNo());
                // 注意：这里不直接返回false，因为订单状态已经更新，需要记录错误但继续处理
            }

            // 4. 退还优惠券
            boolean couponReturned = returnOrderCoupon(order);
            if (!couponReturned) {
                log.error("退还优惠券失败，订单号：{}", order.getOrderNo());
                // 同样不直接返回false
            }

            log.info("订单取消成功，订单号：{}，库存回退：{}，优惠券退还：{}",
                    order.getOrderNo(), stockRestored, couponReturned);
            return true;

        } catch (Exception e) {
            log.error("取消订单失败，订单号：{}", order.getOrderNo(), e);
            throw e; // 重新抛出异常，触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchCancelOrders(List<ShopOrder> orders) {
        if (orders == null || orders.isEmpty()) {
            return 0;
        }

        int successCount = 0;
        for (ShopOrder order : orders) {
            try {
                if (cancelOrder(order)) {
                    successCount++;
                }
            } catch (Exception e) {
                log.error("批量取消订单时发生错误，订单号：{}", order.getOrderNo(), e);
                // 继续处理下一个订单
            }
        }

        log.info("批量取消订单完成，总数：{}，成功：{}", orders.size(), successCount);
        return successCount;
    }

    @Override
    @IgnoreTenant("定时任务需要查询所有租户的超时订单")
    public List<ShopOrder> findExpiredUnpaidOrders(Integer timeoutMinutes, Integer batchSize) {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(timeoutMinutes);

        LambdaQueryWrapper<ShopOrder> queryWrapper = new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getPayStatus, false) // 未支付
                .eq(ShopOrder::getOrderStatus, 0)   // 待支付状态
                .lt(ShopOrder::getCreateTime, expireTime) // 创建时间小于过期时间
                .orderByAsc(ShopOrder::getCreateTime)
                .last("LIMIT " + batchSize);

      final List<ShopOrder> list = shopOrderService.list(queryWrapper);
      System.out.println("定时任务需要查询所有租户的超时订单 list = " + list.size());
      return shopOrderService.list(queryWrapper);
    }

    @Override
    @IgnoreTenant("定时任务需要查询特定租户的超时订单")
    public List<ShopOrder> findExpiredUnpaidOrdersByTenant(Integer tenantId, Integer timeoutMinutes, Integer batchSize) {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(timeoutMinutes);

        LambdaQueryWrapper<ShopOrder> queryWrapper = new LambdaQueryWrapper<ShopOrder>()
                .eq(ShopOrder::getTenantId, tenantId)
                .eq(ShopOrder::getPayStatus, false) // 未支付
                .eq(ShopOrder::getOrderStatus, 0)   // 待支付状态
                .lt(ShopOrder::getCreateTime, expireTime) // 创建时间小于过期时间
                .orderByAsc(ShopOrder::getCreateTime)
                .last("LIMIT " + batchSize);

        return shopOrderService.list(queryWrapper);
    }

    @Override
    public boolean restoreOrderStock(ShopOrder order) {
        try {
            // 获取订单商品信息
            List<ShopOrderGoods> orderGoods = shopOrderGoodsService.list(
                    new LambdaQueryWrapper<ShopOrderGoods>()
                            .eq(ShopOrderGoods::getOrderId, order.getOrderId())
            );

            if (orderGoods == null || orderGoods.isEmpty()) {
                log.warn("订单没有商品信息，订单号：{}", order.getOrderNo());
                return true; // 没有商品信息也算成功
            }

            for (ShopOrderGoods orderGood : orderGoods) {
                // 付款减库存的商品：创建订单时未扣库存，未支付取消时无需回退（避免库存被“加多”）
                try {
                    ShopGoods goods = shopGoodsService.getById(orderGood.getGoodsId());
                    if (goods != null && goods.getDeductStockType() != null && goods.getDeductStockType() == DEDUCT_STOCK_TYPE_PAY) {
                        log.debug("跳过未支付取消的库存回退(付款减库存) - orderId={}, goodsId={}, skuId={}, qty={}",
                                order.getOrderId(), orderGood.getGoodsId(), orderGood.getSkuId(), orderGood.getTotalNum());
                        continue;
                    }
                } catch (Exception e) {
                    // 查不到商品或查询异常时，保持原有回退逻辑，避免出现“库存无法回退”的更坏情况
                    log.warn("读取商品扣库存方式失败，继续执行库存回退 - orderId={}, goodsId={}",
                            order.getOrderId(), orderGood.getGoodsId(), e);
                }

                if (orderGood.getSkuId() != null && orderGood.getSkuId() > 0) {
                    // 多规格商品，恢复SKU库存
                    restoreSkuStock(orderGood);
                } else {
                    // 单规格商品，恢复商品库存
                    restoreGoodsStock(orderGood);
                }
            }

            log.info("订单库存回退成功，订单号：{}，商品数量：{}", order.getOrderNo(), orderGoods.size());
            return true;

        } catch (Exception e) {
            log.error("回退订单库存失败，订单号：{}", order.getOrderNo(), e);
            return false;
        }
    }

    @Override
    public boolean returnOrderCoupon(ShopOrder order) {
        try {
            if (order.getCouponId() == null || order.getCouponId() <= 0) {
                log.debug("订单未使用优惠券，订单号：{}", order.getOrderNo());
                return true; // 没有使用优惠券也算成功
            }

            boolean success = couponStatusService.returnCoupon(order.getOrderId());
            if (success) {
                log.info("订单优惠券退还成功，订单号：{}，优惠券ID：{}", order.getOrderNo(), order.getCouponId());
            } else {
                log.warn("订单优惠券退还失败，订单号：{}，优惠券ID：{}", order.getOrderNo(), order.getCouponId());
            }
            return success;

        } catch (Exception e) {
            log.error("退还订单优惠券失败，订单号：{}", order.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 恢复SKU库存
     */
    private void restoreSkuStock(ShopOrderGoods orderGoods) {
        ShopGoodsSku sku = shopGoodsSkuService.getById(orderGoods.getSkuId());
        if (sku != null) {
            int newStock = (sku.getStock() != null ? sku.getStock() : 0) + orderGoods.getTotalNum();
            sku.setStock(newStock);
            shopGoodsSkuService.updateById(sku);
            log.debug("恢复SKU库存 - SKU ID：{}，恢复数量：{}，当前库存：{}",
                    orderGoods.getSkuId(), orderGoods.getTotalNum(), newStock);
        }
    }

    /**
     * 恢复商品库存
     */
    private void restoreGoodsStock(ShopOrderGoods orderGoods) {
        ShopGoods goods = shopGoodsService.getById(orderGoods.getGoodsId());
        if (goods != null) {
            int newStock = (goods.getStock() != null ? goods.getStock() : 0) + orderGoods.getTotalNum();
            goods.setStock(newStock);
            shopGoodsService.updateById(goods);
            log.debug("恢复商品库存 - 商品ID：{}，恢复数量：{}，当前库存：{}",
                    orderGoods.getGoodsId(), orderGoods.getTotalNum(), newStock);
        }
    }
}
