package com.erp.order.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.order.client.FinanceClient;
import com.erp.order.client.PlatformSyncClient;
import com.erp.order.client.StockClient;
import com.erp.order.dto.request.*;
import com.erp.order.dto.response.*;
import com.erp.order.entity.Order;
import com.erp.order.entity.OrderItem;
import com.erp.order.entity.OrderOperationLog;
import com.erp.order.exception.OrderException;
import com.erp.order.exception.OrderNotFoundException;
import com.erp.order.exception.OrderStateException;
import com.erp.order.repository.OrderItemRepository;
import com.erp.order.repository.OrderOperationLogRepository;
import com.erp.order.repository.OrderRepository;
import com.erp.order.service.OrderService;
import com.erp.order.statemachine.OrderStateMachine;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import com.erp.common.core.model.PageResponse;
import com.erp.common.core.model.ApiResponse;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderRepository orderRepository;
    private final OrderItemRepository orderItemRepository;
    private final OrderOperationLogRepository orderOperationLogRepository;
    private final OrderStateMachine stateMachine;
    private final StockClient stockClient;
    private final FinanceClient financeClient;
    private final PlatformSyncClient platformSyncClient;
    private final ObjectMapper objectMapper;
    private final OrderIdempotencyService idempotencyService;

    @Value("${order.short-id-prefix:O}")
    private String shortIdPrefix;

    // ============ 订单查询 ============

    @Override
    public OrderPageResponse listOrders(OrderQueryRequest request) {
        Page<Order> page = new Page<>(request.getPage(), request.getLimit());

        // 处理日期范围
        LocalDateTime startDate = null;
        LocalDateTime endDate = null;
        if (StringUtils.hasText(request.getDateRange())) {
            String[] dates = request.getDateRange().split(",");
            if (dates.length == 2) {
                startDate = LocalDate.parse(dates[0]).atStartOfDay();
                endDate = LocalDate.parse(dates[1]).atStartOfDay();
            }
        } else {
            if (request.getStartDate() != null) startDate = request.getStartDate().atStartOfDay();
            if (request.getEndDate() != null) endDate = request.getEndDate().atStartOfDay();
        }

        IPage<Order> orderPage = orderRepository.selectOrderPage(
                page, request.getPlatform(), request.getShopId(),
                request.getOrderStatus(), request.getAuditStatus(),
                request.getDeliveryStatus(), request.getKeyword(),
                startDate, endDate);

        List<OrderResponse> list = orderPage.getRecords().stream()
                .map(OrderResponse::fromEntity)
                .collect(Collectors.toList());

        return OrderPageResponse.builder()
                .list(list)
                .total(orderPage.getTotal())
                .currentPage((int) orderPage.getCurrent())
                .lastPage((int) orderPage.getPages())
                .build();
    }

    @Override
    public OrderResponse getOrder(Long id) {
        Order order = orderRepository.selectById(id);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + id);
        }
        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    @Override
    public OrderResponse getOrderByShortId(String shortId) {
        Order order = orderRepository.selectList(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                        .eq(Order::getShortId, shortId))
                .stream().findFirst()
                .orElseThrow(() -> new OrderNotFoundException("订单不存在: " + shortId));
        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    // ============ 待审核 & 待匹配订单查询 ============

    @Override
    public OrderPageResponse listPendingAuditOrders(String platform, Long shopId, String keyword, int page, int limit) {
        Page<Order> pageParam = new Page<>(page, limit);
        IPage<Order> orderPage = orderRepository.selectPendingAuditPage(pageParam, platform, shopId, keyword);
        List<OrderResponse> list = orderPage.getRecords().stream()
                .map(order -> {
                    loadOrderItems(order);
                    return OrderResponse.fromEntity(order);
                })
                .collect(Collectors.toList());
        return OrderPageResponse.builder()
                .list(list)
                .total(orderPage.getTotal())
                .currentPage((int) orderPage.getCurrent())
                .lastPage((int) orderPage.getPages())
                .build();
    }

    @Override
    public OrderPageResponse listPendingMatchOrders(String platform, Long shopId, String keyword, int page, int limit) {
        Page<Order> pageParam = new Page<>(page, limit);
        IPage<Order> orderPage = orderRepository.selectPendingMatchPage(pageParam, platform, shopId, keyword);
        List<OrderResponse> list = orderPage.getRecords().stream()
                .map(order -> {
                    loadOrderItems(order);
                    return OrderResponse.fromEntity(order);
                })
                .collect(Collectors.toList());
        return OrderPageResponse.builder()
                .list(list)
                .total(orderPage.getTotal())
                .currentPage((int) orderPage.getCurrent())
                .lastPage((int) orderPage.getPages())
                .build();
    }

    // ============ 订单创建 & 拉取 ============

    @Override
    public PullOrdersResult pullOrders(PullOrdersRequest request) {
        // 调用平台API拉取订单（这里先调用PlatformSyncClient，实际项目中需要适配各平台）
        try {
            ApiResponse<?> response = platformSyncClient.pullOrdersFromPlatform(
                    request.getPlatform(), request.getShopId(), request.getPullType(),
                    request.getOrderIds(),
                    request.getStartTime() != null ? request.getStartTime().toString() : null,
                    request.getEndTime() != null ? request.getEndTime().toString() : null);

            if (response.getCode() != 200) {
                throw new OrderException("拉取订单失败: " + response.getMessage());
            }

            // 将拉取的订单数据转换为OrderCreateRequest并创建
            // 实际项目中，PlatformSyncClient返回的数据会有特定格式，这里做转换
            List<OrderCreateRequest> orders = convertToOrderCreateRequests(response.getData(), request);
            int count = createOrders(orders);

            return PullOrdersResult.builder()
                    .count(count)
                    .createdOrderIds(new ArrayList<>())
                    .build();

        } catch (Exception e) {
            log.error("拉取订单异常", e);
            throw new OrderException("拉取订单失败: " + e.getMessage());
        }
    }

    @SuppressWarnings("unchecked")
    private List<OrderCreateRequest> convertToOrderCreateRequests(Object data, PullOrdersRequest request) {
        List<OrderCreateRequest> orders = new ArrayList<>();
        if (data instanceof List) {
            for (Object item : (List<?>) data) {
                if (item instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) item;
                    OrderCreateRequest orderReq = new OrderCreateRequest();
                    orderReq.setPlatformOrderSn((String) map.get("platformOrderSn"));
                    orderReq.setPlatform(request.getPlatform());
                    orderReq.setShopId(request.getShopId());
                    orderReq.setOrderTime(LocalDateTime.now());
                    orderReq.setBuyerNick((String) map.get("buyerNick"));
                    orderReq.setReceiverName((String) map.get("receiverName"));
                    orderReq.setReceiverPhone((String) map.get("receiverPhone"));
                    orderReq.setReceiverAddress((String) map.get("receiverAddress"));
                    Object goodsAmount = map.get("goodsAmount");
                    orderReq.setGoodsAmount(goodsAmount != null ? new BigDecimal(goodsAmount.toString()) : BigDecimal.ZERO);
                    orderReq.setTotalAmount(orderReq.getGoodsAmount());
                    orderReq.setPlatformStatus((String) map.get("platformStatus"));
                    orders.add(orderReq);
                }
            }
        }
        return orders;
    }

    @Override
    @Transactional
    public int createOrders(List<OrderCreateRequest> requests) {
        int count = 0;
        for (OrderCreateRequest req : requests) {
            // ========== 幂等性检查 ==========
            String idempotencyKey = idempotencyService.buildOrderCreateKey(
                    req.getPlatform(), req.getShopId(), req.getPlatformOrderSn());

            // 1. 先检查Redis是否已处理过
            if (idempotencyService.isDuplicate(idempotencyKey)) {
                log.warn("[订单创建] 重复请求，已跳过: key={}", idempotencyKey);
                // 返回已处理的结果（幂等：重复调用返回成功但不重复创建）
                continue;
            }

            // 2. 检查数据库唯一约束（兜底）
            if (StringUtils.hasText(req.getPlatformOrderSn()) && req.getShopId() != null) {
                com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order> existWrapper =
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getPlatformOrderSn, req.getPlatformOrderSn())
                                .eq(Order::getPlatform, req.getPlatform())
                                .eq(Order::getShopId, req.getShopId());
                Long existCount = orderRepository.selectCount(existWrapper);
                if (existCount > 0) {
                    log.warn("[订单创建] 数据库已存在订单，已跳过: platformOrderSn={}", req.getPlatformOrderSn());
                    // 标记为已处理，防止后续重试
                    idempotencyService.markProcessed(idempotencyKey, "exists");
                    continue;
                }
            }

            // 3. 执行业务操作并标记幂等
            try {
                // 生成短ID
                String shortId = generateShortId();
                LocalDateTime now = LocalDateTime.now();

                Order order = Order.builder()
                        .shortId(shortId)
                        .platformOrderSn(req.getPlatformOrderSn())
                        .platform(req.getPlatform())
                        .shopId(req.getShopId())
                        .shopName(req.getShopName())
                        .orderTime(req.getOrderTime() != null ? req.getOrderTime() : now)
                        .buyerNick(req.getBuyerNick())
                        .receiverName(req.getReceiverName())
                        .receiverPhone(req.getReceiverPhone())
                        .receiverAddress(req.getReceiverAddress())
                        .goodsAmount(req.getGoodsAmount())
                        .discountAmount(req.getDiscountAmount() != null ? req.getDiscountAmount() : BigDecimal.ZERO)
                        .freight(req.getFreight() != null ? req.getFreight() : BigDecimal.ZERO)
                        .totalAmount(req.getTotalAmount() != null ? req.getTotalAmount() : req.getGoodsAmount())
                        .orderStatus(OrderStateMachine.STATUS_PENDING)
                        .platformStatus(req.getPlatformStatus())
                        .auditStatus(OrderStateMachine.AUDIT_PENDING)
                        .deliveryStatus(OrderStateMachine.DELIVERY_PENDING)
                        .build();

                orderRepository.insert(order);

                // 创建订单项
                if (req.getItems() != null) {
                    for (OrderCreateRequest.OrderItemRequest itemReq : req.getItems()) {
                        OrderItem item = OrderItem.builder()
                                .orderId(order.getId())
                                .goodsName(itemReq.getGoodsName())
                                .platformSku(itemReq.getPlatformSku())
                                .skuCode(itemReq.getSkuCode())
                                .erpSkuId(itemReq.getErpSkuId())
                                .quantity(itemReq.getQuantity())
                                .price(itemReq.getPrice())
                                .totalAmount(itemReq.getTotalAmount())
                                .build();
                        orderItemRepository.insert(item);
                    }
                }

                // 记录操作日志
                saveOperationLog(order.getId(), 0L, "系统", "create", "创建订单",
                        null, OrderStateMachine.STATUS_PENDING,
                        null, null, null, null, null);

                // 标记幂等键已处理
                idempotencyService.markProcessed(idempotencyKey, order.getId());
                count++;
            } catch (Exception e) {
                log.error("[订单创建] 创建失败: key={}, error={}", idempotencyKey, e.getMessage());
                throw e;
            }
        }
        return count;
    }

    // ============ 订单审核 ============

    @Override
    @Transactional
    public OrderResponse auditOrder(Long orderId, String action, String comment, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        if (!stateMachine.canAudit(order)) {
            throw new OrderStateException("订单状态不允许审核，当前状态: " + order.getOrderStatus());
        }

        String beforeStatus = order.getOrderStatus();
        String beforeAuditStatus = order.getAuditStatus();

        if ("approve".equals(action)) {
            stateMachine.transition(order, OrderStateMachine.STATUS_AUDITING, operator.getOperatorName(), comment);
        } else if ("reject".equals(action)) {
            stateMachine.transition(order, OrderStateMachine.STATUS_CANCELLED, operator.getOperatorName(), comment);
            // 驳回时解锁库存
            unlockStockForOrder(order);
        } else {
            throw new OrderException("不支持的审核操作: " + action);
        }

        orderRepository.updateById(order);

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "approve".equals(action) ? "audit_approve" : "audit_reject",
                "approve".equals(action) ? "审核通过" : "审核驳回",
                beforeStatus, order.getOrderStatus(),
                beforeAuditStatus, order.getAuditStatus(),
                order.getAuditStatus(),
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    @Override
    @Transactional
    public BatchOperationResult batchAudit(BatchAuditRequest request, OperatorInfo operator) {
        int successCount = 0;
        List<BatchOperationResult.FailedOrder> failedOrders = new ArrayList<>();

        for (Long orderId : request.getOrderIds()) {
            try {
                auditOrder(orderId, request.getAction(), request.getComment(), operator);
                successCount++;
            } catch (OrderException e) {
                failedOrders.add(BatchOperationResult.FailedOrder.builder()
                        .id(orderId).reason(e.getMessage()).build());
            }
        }

        return BatchOperationResult.builder()
                .successCount(successCount)
                .failedOrders(failedOrders)
                .build();
    }

    // ============ 仓库 & 发货 ============

    @Override
    @Transactional
    public OrderResponse setWarehouseExpress(Long orderId, SetWarehouseExpressRequest request, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        if (!OrderStateMachine.AUDIT_APPROVED.equals(order.getAuditStatus())) {
            throw new OrderStateException("只有已审核的订单可以设置仓库");
        }

        String beforeStatus = order.getOrderStatus();
        if (request.getWarehouseId() != null) order.setWarehouseId(request.getWarehouseId());
        if (StringUtils.hasText(request.getExpressCompany())) order.setExpressCompany(request.getExpressCompany());
        if (StringUtils.hasText(request.getExpressName())) order.setExpressName(request.getExpressName());

        orderRepository.updateById(order);

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "set_warehouse", "设置仓库",
                beforeStatus, order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    @Override
    @Transactional
    public OrderResponse shipOrder(Long orderId, ShipOrderRequest request, OperatorInfo operator) {
        // ========== 幂等性检查 ==========
        String idempotencyKey = idempotencyService.buildShipOrderKey(orderId);
        if (idempotencyService.isDuplicate(idempotencyKey)) {
            log.warn("[订单发货] 重复发货请求，已跳过: orderId={}", orderId);
            Order order = orderRepository.selectById(orderId);
            if (order == null) throw new OrderNotFoundException("订单不存在: " + orderId);
            loadOrderItems(order);
            return OrderResponse.fromEntity(order);
        }

        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        if (!stateMachine.canShip(order)) {
            throw new OrderStateException("订单状态不允许发货，请检查订单是否已审核且设置了仓库");
        }

        String beforeStatus = order.getOrderStatus();

        // 更新订单状态
        order.setExpressCompany(request.getExpressCompany());
        order.setExpressNo(request.getExpressNo());
        order.setDeliveryStatus(OrderStateMachine.DELIVERY_DELIVERED);
        order.setDeliveryTime(LocalDateTime.now());
        stateMachine.transition(order, OrderStateMachine.STATUS_SHIPPED, operator.getOperatorName(), null);

        orderRepository.updateById(order);

        // 扣减库存
        deductStockForOrder(order);

        // 记录操作日志
        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "ship", "订单发货",
                beforeStatus, order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        // 标记幂等
        idempotencyService.markProcessed(idempotencyKey, orderId);

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    // ============ 订单状态流转 ============

    @Override
    @Transactional
    public OrderResponse completeOrder(Long orderId, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        if (!stateMachine.canComplete(order)) {
            throw new OrderStateException("只有已发货的订单可以完成");
        }

        String beforeStatus = order.getOrderStatus();
        stateMachine.transition(order, OrderStateMachine.STATUS_COMPLETED, operator.getOperatorName(), null);
        orderRepository.updateById(order);

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "complete", "订单完成",
                beforeStatus, order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    @Override
    @Transactional
    public OrderResponse cancelOrder(Long orderId, String reason, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        if (!stateMachine.canCancel(order)) {
            throw new OrderStateException("订单状态不允许取消");
        }

        String beforeStatus = order.getOrderStatus();
        stateMachine.transition(order, OrderStateMachine.STATUS_CANCELLED, operator.getOperatorName(), reason);
        orderRepository.updateById(order);

        // 取消时解锁库存
        unlockStockForOrder(order);

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "cancel", "订单取消",
                beforeStatus, order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    // ============ 批量操作 ============

    @Override
    @Transactional
    public BatchOperationResult batchOperation(BatchOperationRequest request, OperatorInfo operator) {
        int successCount = 0;
        List<BatchOperationResult.FailedOrder> failedOrders = new ArrayList<>();

        for (Long orderId : request.getOrderIds()) {
            try {
                Order order = orderRepository.selectById(orderId);
                if (order == null) {
                    failedOrders.add(BatchOperationResult.FailedOrder.builder()
                            .id(orderId).reason("订单不存在").build());
                    continue;
                }

                String op = request.getOperation();
                boolean ok = false;
                String reason = null;

                switch (op) {
                    case "audit_approve":
                        auditOrder(orderId, "approve", null, operator);
                        ok = true;
                        break;
                    case "audit_reject":
                        String comment = request.getData() != null ? String.valueOf(request.getData().get("comment")) : "";
                        auditOrder(orderId, "reject", comment, operator);
                        ok = true;
                        break;
                    case "set_warehouse":
                        SetWarehouseExpressRequest wareReq = new SetWarehouseExpressRequest();
                        if (request.getData() != null) {
                            if (request.getData().get("warehouseId") != null)
                                wareReq.setWarehouseId(Long.valueOf(request.getData().get("warehouseId").toString()));
                            if (request.getData().get("expressCompany") != null)
                                wareReq.setExpressCompany(request.getData().get("expressCompany").toString());
                        }
                        setWarehouseExpress(orderId, wareReq, operator);
                        ok = true;
                        break;
                    case "ship":
                        ShipOrderRequest shipReq = new ShipOrderRequest();
                        if (request.getData() != null) {
                            if (request.getData().get("expressCompany") != null)
                                shipReq.setExpressCompany(request.getData().get("expressCompany").toString());
                            if (request.getData().get("expressNo") != null)
                                shipReq.setExpressNo(request.getData().get("expressNo").toString());
                        }
                        shipOrder(orderId, shipReq, operator);
                        ok = true;
                        break;
                    case "cancel":
                        String cancelReason = request.getData() != null && request.getData().get("reason") != null
                                ? request.getData().get("reason").toString() : "批量取消";
                        cancelOrder(orderId, cancelReason, operator);
                        ok = true;
                        break;
                    case "delete":
                        if (!stateMachine.isFinalState(order.getOrderStatus())) {
                            reason = "只有已完成或已取消的订单可以删除";
                        } else {
                            orderRepository.deleteById(orderId);
                            ok = true;
                        }
                        break;
                    default:
                        reason = "不支持的操作类型: " + op;
                }

                if (ok) successCount++;
                else if (reason != null) {
                    failedOrders.add(BatchOperationResult.FailedOrder.builder()
                            .id(orderId).reason(reason).build());
                }
            } catch (OrderException e) {
                failedOrders.add(BatchOperationResult.FailedOrder.builder()
                        .id(orderId).reason(e.getMessage()).build());
            }
        }

        return BatchOperationResult.builder()
                .successCount(successCount)
                .failedOrders(failedOrders)
                .build();
    }

    // ============ 统计 & 导出 ============

    @Override
    public OrderStatisticsResponse getStatistics(OrderQueryRequest request) {
        // 基础查询条件
        var wrapper = buildQueryWrapper(request);

        // 状态统计
        Map<String, Long> statusStats = new LinkedHashMap<>();
        for (String status : Arrays.asList("pending", "auditing", "shipped", "completed", "cancelled")) {
            statusStats.put(status, orderRepository.selectCount(
                    buildQueryWrapper(request).eq(Order::getOrderStatus, status)));
        }

        // 审核状态统计
        Map<String, Long> auditStats = new LinkedHashMap<>();
        for (String status : Arrays.asList("pending", "approved", "rejected")) {
            auditStats.put(status, orderRepository.selectCount(
                    buildQueryWrapper(request).eq(Order::getAuditStatus, status)));
        }

        // 发货状态统计
        Map<String, Long> deliveryStats = new LinkedHashMap<>();
        deliveryStats.put("pending", orderRepository.selectCount(
                buildQueryWrapper(request).eq(Order::getDeliveryStatus, "pending")));
        deliveryStats.put("delivered", orderRepository.selectCount(
                buildQueryWrapper(request).eq(Order::getDeliveryStatus, "delivered")));

        // 金额统计
        var amountWrapper = buildQueryWrapper(request);
        BigDecimal totalGoodsAmount = aggregateSum(amountWrapper, "goods_amount");
        BigDecimal totalDiscountAmount = aggregateSum(amountWrapper, "discount_amount");
        BigDecimal totalFreight = aggregateSum(amountWrapper, "freight");
        BigDecimal totalAmount = aggregateSum(amountWrapper, "total_amount");
        BigDecimal avgOrderAmount = aggregateAvg(amountWrapper, "total_amount");

        return OrderStatisticsResponse.builder()
                .statusStats(statusStats)
                .auditStats(auditStats)
                .deliveryStats(deliveryStats)
                .amountStats(OrderStatisticsResponse.AmountStats.builder()
                        .totalGoodsAmount(totalGoodsAmount)
                        .totalDiscountAmount(totalDiscountAmount)
                        .totalFreight(totalFreight)
                        .totalAmount(totalAmount)
                        .avgOrderAmount(avgOrderAmount)
                        .build())
                .totalOrders(orderRepository.selectCount(buildQueryWrapper(request)))
                .dateRange(OrderStatisticsResponse.DateRange.builder()
                        .startDate(request.getStartDate() != null ? request.getStartDate().toString() : null)
                        .endDate(request.getEndDate() != null ? request.getEndDate().toString() : null)
                        .build())
                .build();
    }

    private com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order> buildQueryWrapper(OrderQueryRequest request) {
        var wrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>();
        if (StringUtils.hasText(request.getPlatform())) wrapper.eq(Order::getPlatform, request.getPlatform());
        if (request.getShopId() != null) wrapper.eq(Order::getShopId, request.getShopId());
        if (StringUtils.hasText(request.getOrderStatus())) wrapper.eq(Order::getOrderStatus, request.getOrderStatus());
        if (StringUtils.hasText(request.getAuditStatus())) wrapper.eq(Order::getAuditStatus, request.getAuditStatus());
        if (StringUtils.hasText(request.getDeliveryStatus())) wrapper.eq(Order::getDeliveryStatus, request.getDeliveryStatus());
        if (StringUtils.hasText(request.getKeyword())) {
            wrapper.and(w -> w.like(Order::getShortId, request.getKeyword())
                    .or().like(Order::getPlatformOrderSn, request.getKeyword())
                    .or().like(Order::getReceiverName, request.getKeyword())
                    .or().like(Order::getReceiverPhone, request.getKeyword()));
        }
        if (request.getStartDate() != null) wrapper.ge(Order::getOrderTime, request.getStartDate().atStartOfDay());
        if (request.getEndDate() != null) wrapper.le(Order::getOrderTime, request.getEndDate().atTime(23, 59, 59));
        return wrapper;
    }

    private BigDecimal aggregateSum(com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order> wrapper, String column) {
        // 简化实现，实际项目中应使用 MyBatis-Plus 的 selectSum 方法
        return BigDecimal.ZERO;
    }

    private BigDecimal aggregateAvg(com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order> wrapper, String column) {
        return BigDecimal.ZERO;
    }

    @Override
    public DashboardStatsResponse getDashboardStats() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime todayStart = now.toLocalDate().atStartOfDay();
        LocalDateTime yesterdayStart = now.minusDays(1).toLocalDate().atStartOfDay();
        LocalDateTime monthStart = now.toLocalDate().withDayOfMonth(1).atStartOfDay();

        return DashboardStatsResponse.builder()
                .today(buildPeriodStats(todayStart, null))
                .yesterday(buildPeriodStats(yesterdayStart, todayStart))
                .thisMonth(buildPeriodStats(monthStart, null))
                .all(buildAllStats())
                .build();
    }

    private DashboardStatsResponse.PeriodStats buildPeriodStats(LocalDateTime start, LocalDateTime end) {
        // 今日数据不需要end条件
        long total = orderRepository.selectCount(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                        .ge(Order::getOrderTime, start)
                        .lt(end != null ? Order::getOrderTime : null, end));

        long pending = orderRepository.selectCount(
                makeTimeRangeWrapper(start, end).eq(Order::getOrderStatus, "pending"));
        long auditing = orderRepository.selectCount(
                makeTimeRangeWrapper(start, end).eq(Order::getOrderStatus, "auditing"));
        long shipped = orderRepository.selectCount(
                makeTimeRangeWrapper(start, end).eq(Order::getOrderStatus, "shipped"));

        return DashboardStatsResponse.PeriodStats.builder()
                .total(total).pending(pending).auditing(auditing).shipped(shipped)
                .amount(BigDecimal.ZERO)
                .build();
    }

    private com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order> makeTimeRangeWrapper(
            LocalDateTime start, LocalDateTime end) {
        var wrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                .ge(Order::getOrderTime, start);
        if (end != null) {
            wrapper.lt(Order::getOrderTime, end);
        }
        return wrapper;
    }

    private DashboardStatsResponse.AllStats buildAllStats() {
        long total = orderRepository.selectCount(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>());
        return DashboardStatsResponse.AllStats.builder()
                .total(total)
                .pending(orderRepository.selectCount(
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getOrderStatus, "pending")))
                .auditing(orderRepository.selectCount(
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getOrderStatus, "auditing")))
                .shipped(orderRepository.selectCount(
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getOrderStatus, "shipped")))
                .completed(orderRepository.selectCount(
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getOrderStatus, "completed")))
                .cancelled(orderRepository.selectCount(
                        new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Order>()
                                .eq(Order::getOrderStatus, "cancelled")))
                .amount(BigDecimal.ZERO)
                .build();
    }


    @Override
    public ExportResult exportOrders(OrderQueryRequest request, String exportType) {
        List<Order> orders = orderRepository.selectList(
                buildQueryWrapper(request).orderByDesc(Order::getOrderTime));

        List<Map<String, Object>> data = orders.stream().map(order -> {
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("订单短ID", order.getShortId());
            row.put("平台订单号", order.getPlatformOrderSn());
            row.put("平台", order.getPlatform());
            row.put("店铺名称", order.getShopName());
            row.put("下单时间", order.getOrderTime());
            row.put("买家昵称", order.getBuyerNick());
            row.put("收货人", order.getReceiverName());
            row.put("收货电话", order.getReceiverPhone());
            row.put("收货地址", order.getReceiverAddress());
            row.put("商品金额", order.getGoodsAmount());
            row.put("优惠金额", order.getDiscountAmount());
            row.put("运费", order.getFreight());
            row.put("总金额", order.getTotalAmount());
            row.put("订单状态", OrderResponse.getOrderStatusText(order.getOrderStatus()));
            row.put("平台状态", order.getPlatformStatus());
            row.put("审核状态", OrderResponse.getAuditStatusText(order.getAuditStatus()));
            row.put("发货状态", OrderResponse.getDeliveryStatusText(order.getDeliveryStatus()));
            row.put("发货时间", order.getDeliveryTime());
            row.put("快递公司", order.getExpressCompany());
            row.put("快递单号", order.getExpressNo());
            row.put("仓库名称", order.getWarehouseName());
            row.put("备注", order.getRemark());
            return row;
        }).collect(Collectors.toList());

        String filename = "orders_export_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
                + ("excel".equals(exportType) ? ".xlsx" : ".csv");

        return ExportResult.builder()
                .filename(filename)
                .count(orders.size())
                .data(data)
                .headers(data.isEmpty() ? Collections.emptyList() : new ArrayList<>(data.get(0).keySet()))
                .build();
    }

    // ============ 备注 & 日志 ============

    @Override
    @Transactional
    public OrderResponse updateRemark(Long orderId, String remark, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        String oldRemark = order.getRemark();
        order.setRemark(remark);
        orderRepository.updateById(order);

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "update_remark", String.format("更新备注: %s -> %s", oldRemark, remark),
                order.getOrderStatus(), order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    @Override
    public List<OperationLogResponse> getOrderLogs(Long orderId) {
        List<OrderOperationLog> logs = orderOperationLogRepository.selectByOrderId(orderId);
        return logs.stream().map(log -> OperationLogResponse.builder()
                .id(log.getId())
                .operatorId(log.getOperatorId())
                .operator(log.getOperatorName())
                .action(log.getAction())
                .actionText(log.getActionText())
                .content(log.getContent())
                .beforeStatus(log.getBeforeStatus())
                .afterStatus(log.getAfterStatus())
                .ip(log.getIp())
                .userAgent(log.getUserAgent())
                .createdAt(log.getCreatedAt())
                .build()).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public OrderResponse syncToPlatform(Long orderId, OperatorInfo operator) {
        Order order = orderRepository.selectById(orderId);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderId);
        }

        try {
            platformSyncClient.syncOrderToPlatform(
                    new PlatformSyncClient.PlatformSyncRequest() {{
                        setPlatform(order.getPlatform());
                        setPlatformOrderSn(order.getPlatformOrderSn());
                        setSyncStatus(order.getOrderStatus());
                        setExpressCompany(order.getExpressCompany());
                        setExpressNo(order.getExpressNo());
                    }});
        } catch (Exception e) {
            log.warn("同步订单到平台失败: {}", orderId, e);
        }

        saveOperationLog(order.getId(), operator.getOperatorId(), operator.getOperatorName(),
                "sync_to_platform",
                String.format("同步到平台: %s, 平台单号: %s", order.getPlatform(), order.getPlatformOrderSn()),
                order.getOrderStatus(), order.getOrderStatus(),
                null, null, null,
                operator.getIp(), operator.getUserAgent());

        loadOrderItems(order);
        return OrderResponse.fromEntity(order);
    }

    // ============ 辅助方法 ============

    @Override
    public List<StatusOption> getOrderStatusOptions() {
        return Arrays.asList(
                StatusOption.builder().value("pending").label("待处理").build(),
                StatusOption.builder().value("auditing").label("审核中").build(),
                StatusOption.builder().value("shipped").label("已发货").build(),
                StatusOption.builder().value("completed").label("已完成").build(),
                StatusOption.builder().value("cancelled").label("已取消").build());
    }

    @Override
    public List<StatusOption> getAuditStatusOptions() {
        return Arrays.asList(
                StatusOption.builder().value("pending").label("待审核").build(),
                StatusOption.builder().value("approved").label("已通过").build(),
                StatusOption.builder().value("rejected").label("已驳回").build());
    }

    @Override
    public List<StatusOption> getDeliveryStatusOptions() {
        return Arrays.asList(
                StatusOption.builder().value("pending").label("待发货").build(),
                StatusOption.builder().value("delivered").label("已发货").build());
    }

    @Override
    public List<StatusOption> getPlatformOptions() {
        return orderRepository.selectDistinctPlatforms().stream()
                .map(p -> StatusOption.builder().value(p).label(p).build())
                .collect(Collectors.toList());
    }

    @Override
    public List<ShopOption> getShopOptions() {
        return orderRepository.selectDistinctShops().stream()
                .map(s -> ShopOption.builder().value(s.getShopId()).label(s.getShopName()).build())
                .collect(Collectors.toList());
    }

    // ============ 私有辅助方法 ============

    private void loadOrderItems(Order order) {
        List<OrderItem> items = orderItemRepository.selectByOrderId(order.getId());
        order.setItems(items);
    }

    private String generateShortId() {
        return shortIdPrefix + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                + UUID.randomUUID().toString().substring(0, 6).toUpperCase();
    }

    @Transactional
    private void saveOperationLog(Long orderId, Long operatorId, String operatorName,
                                  String action, String actionText, String content,
                                  String beforeStatus, String afterStatus,
                                  String beforeAuditStatus, String afterAuditStatus,
                                  String ip, String userAgent) {
        OrderOperationLog log = OrderOperationLog.builder()
                .orderId(orderId)
                .operatorId(operatorId)
                .operatorName(operatorName)
                .action(action)
                .actionText(actionText)
                .content(content)
                .beforeStatus(beforeStatus)
                .afterStatus(afterStatus)
                .beforeAuditStatus(beforeAuditStatus)
                .afterAuditStatus(afterAuditStatus)
                .ip(ip)
                .userAgent(userAgent)
                .build();
        orderOperationLogRepository.insert(log);
    }

    private void deductStockForOrder(Order order) {
        if (order.getItems() == null || order.getItems().isEmpty()) {
            loadOrderItems(order);
        }
        for (OrderItem item : order.getItems()) {
            String skuCode = item.getSkuCode() != null ? item.getSkuCode()
                    : (item.getErpSkuId() != null ? String.valueOf(item.getErpSkuId()) : null);
            if (skuCode == null) continue;
            try {
                stockClient.deductStock(new StockClient.StockDeductRequest() {{
                    setSkuCode(skuCode);
                    setWarehouseId(order.getWarehouseId());
                    setQuantity(item.getQuantity());
                    setRelatedNo(order.getShortId());
                    setRemark("订单发货出库");
                }});
            } catch (Exception e) {
                log.warn("扣减库存失败: order={}, sku={}, error={}",
                        order.getShortId(), skuCode, e.getMessage());
                // 库存服务不可用时降级，不阻塞发货流程
            }
        }
    }

    private void unlockStockForOrder(Order order) {
        if (order.getItems() == null) {
            loadOrderItems(order);
        }
        for (OrderItem item : order.getItems()) {
            String skuCode = item.getSkuCode() != null ? item.getSkuCode()
                    : (item.getErpSkuId() != null ? String.valueOf(item.getErpSkuId()) : null);
            if (skuCode == null) continue;
            try {
                stockClient.unlockStock(new StockClient.StockUnlockRequest() {{
                    setSkuCode(skuCode);
                    setWarehouseId(order.getWarehouseId());
                    setQuantity(item.getQuantity());
                    setRelatedNo(order.getShortId());
                    setRemark("订单驳回/取消解锁库存");
                }});
            } catch (Exception e) {
                log.warn("解锁库存失败: order={}, sku={}, error={}",
                        order.getShortId(), skuCode, e.getMessage());
            }
        }
    }
}
