package com.example.demo.service;

import com.example.demo.model.*;
import com.example.demo.repository.OrderItemRepository;
import com.example.demo.repository.OrderRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
@Transactional
public class OrderService {
    
    private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private OrderItemRepository orderItemRepository;
    
    /**
     * 创建订单
     */
    public Order createOrder(Order order) {
        try {
            // 设置订单状态
            if (order.getStatus() == null) {
                order.setStatus(OrderStatus.PENDING);
            }
            
            // 设置默认货币
            if (order.getCurrency() == null || order.getCurrency().isEmpty()) {
                order.setCurrency("CNY");
            }
            
            // 设置默认订单类型
            if (order.getOrderType() == null) {
                order.setOrderType(OrderType.PRODUCT);
            }
            
            // 计算订单总金额
            if (order.getOrderItems() != null && !order.getOrderItems().isEmpty()) {
                BigDecimal totalAmount = order.getOrderItems().stream()
                        .map(OrderItem::getSubtotal)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                order.setTotalAmount(totalAmount);
            }
            
            // 临时保存订单项，避免级联保存问题
            List<OrderItem> tempOrderItems = order.getOrderItems();
            order.setOrderItems(new ArrayList<>()); // 清空订单项
            
            // 先保存订单（获得ID）
            Order savedOrder = orderRepository.save(order);
            
            // 再保存订单项，设置正确的order_id
            if (tempOrderItems != null && !tempOrderItems.isEmpty()) {
                List<OrderItem> savedOrderItems = new ArrayList<>();
                for (OrderItem item : tempOrderItems) {
                    item.setOrder(savedOrder); // 设置关联的订单
                    OrderItem savedItem = orderItemRepository.save(item);
                    savedOrderItems.add(savedItem);
                }
                savedOrder.setOrderItems(savedOrderItems);
            }
            
            logger.info("订单创建成功，订单号：{}", savedOrder.getOrderNumber());
            return savedOrder;
            
        } catch (Exception e) {
            logger.error("创建订单失败：", e);
            throw new RuntimeException("创建订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据ID查找订单
     */
    @Transactional(readOnly = true)
    public Optional<Order> findById(Long id) {
        return orderRepository.findById(id);
    }
    
    /**
     * 根据订单号查找订单
     */
    @Transactional(readOnly = true)
    public Optional<Order> findByOrderNumber(String orderNumber) {
        return orderRepository.findByOrderNumber(orderNumber);
    }
    
    /**
     * 根据用户ID查找订单
     */
    @Transactional(readOnly = true)
    public List<Order> findByUserId(Long userId) {
        return orderRepository.findByUserId(userId);
    }
    
    /**
     * 根据用户ID分页查找订单
     */
    @Transactional(readOnly = true)
    public Page<Order> findByUserId(Long userId, Pageable pageable) {
        return orderRepository.findByUserId(userId, pageable);
    }
    
    /**
     * 查找所有订单
     */
    @Transactional(readOnly = true)
    public List<Order> findAll() {
        return orderRepository.findAll();
    }
    
    /**
     * 分页查找所有订单
     */
    @Transactional(readOnly = true)
    public Page<Order> findAll(Pageable pageable) {
        return orderRepository.findAll(pageable);
    }
    
    /**
     * 根据状态查找订单
     */
    @Transactional(readOnly = true)
    public List<Order> findByStatus(OrderStatus status) {
        return orderRepository.findByStatus(status);
    }
    
    /**
     * 根据状态分页查找订单
     */
    @Transactional(readOnly = true)
    public Page<Order> findByStatus(OrderStatus status, Pageable pageable) {
        return orderRepository.findByStatus(status, pageable);
    }
    
    /**
     * 更新订单状态
     */
    public Order updateOrderStatus(Long orderId, OrderStatus newStatus) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            OrderStatus oldStatus = order.getStatus();
            order.setStatus(newStatus);
            
            // 设置相应的时间戳
            LocalDateTime now = LocalDateTime.now();
            switch (newStatus) {
                case PAID:
                    order.setPaidAt(now);
                    break;
                case SHIPPED:
                    order.setShippedAt(now);
                    break;
                case DELIVERED:
                    order.setDeliveredAt(now);
                    break;
                case COMPLETED:
                    order.setDeliveredAt(now);
                    break;
                case CANCELLED:
                    order.setCancelledAt(now);
                    break;
            }
            
            Order updatedOrder = orderRepository.save(order);
            logger.info("订单状态更新成功，订单号：{}，状态：{} -> {}", 
                order.getOrderNumber(), oldStatus, newStatus);
            
            return updatedOrder;
            
        } catch (Exception e) {
            logger.error("更新订单状态失败：", e);
            throw new RuntimeException("更新订单状态失败：" + e.getMessage());
        }
    }
    
    /**
     * 取消订单
     */
    public Order cancelOrder(Long orderId, String reason) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            if (!order.canCancel()) {
                throw new RuntimeException("订单当前状态不允许取消");
            }
            
            order.setStatus(OrderStatus.CANCELLED);
            order.setCancelledAt(LocalDateTime.now());
            if (reason != null && !reason.isEmpty()) {
                order.setNotes((order.getNotes() != null ? order.getNotes() + "\n" : "") + 
                    "取消原因：" + reason);
            }
            
            Order cancelledOrder = orderRepository.save(order);
            logger.info("订单取消成功，订单号：{}", order.getOrderNumber());
            
            return cancelledOrder;
            
        } catch (Exception e) {
            logger.error("取消订单失败：", e);
            throw new RuntimeException("取消订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 确认订单支付
     */
    public Order confirmPayment(Long orderId, String paymentId) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            if (!order.canPay()) {
                throw new RuntimeException("订单当前状态不允许支付");
            }
            
            order.setStatus(OrderStatus.PAID);
            order.setPaidAt(LocalDateTime.now());
            
            Order paidOrder = orderRepository.save(order);
            logger.info("订单支付确认成功，订单号：{}，支付ID：{}", 
                order.getOrderNumber(), paymentId);
            
            return paidOrder;
            
        } catch (Exception e) {
            logger.error("确认订单支付失败：", e);
            throw new RuntimeException("确认订单支付失败：" + e.getMessage());
        }
    }
    
    /**
     * 发货
     */
    public Order shipOrder(Long orderId, String trackingNumber) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            if (!order.canShip()) {
                throw new RuntimeException("订单当前状态不允许发货");
            }
            
            order.setStatus(OrderStatus.SHIPPED);
            order.setShippedAt(LocalDateTime.now());
            if (trackingNumber != null && !trackingNumber.isEmpty()) {
                order.setNotes((order.getNotes() != null ? order.getNotes() + "\n" : "") + 
                    "物流单号：" + trackingNumber);
            }
            
            Order shippedOrder = orderRepository.save(order);
            logger.info("订单发货成功，订单号：{}", order.getOrderNumber());
            
            return shippedOrder;
            
        } catch (Exception e) {
            logger.error("订单发货失败：", e);
            throw new RuntimeException("订单发货失败：" + e.getMessage());
        }
    }
    
    /**
     * 完成订单
     */
    public Order completeOrder(Long orderId) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            if (!order.canComplete()) {
                throw new RuntimeException("订单当前状态不允许完成");
            }
            
            order.setStatus(OrderStatus.COMPLETED);
            order.setDeliveredAt(LocalDateTime.now());
            
            Order completedOrder = orderRepository.save(order);
            logger.info("订单完成成功，订单号：{}", order.getOrderNumber());
            
            return completedOrder;
            
        } catch (Exception e) {
            logger.error("完成订单失败：", e);
            throw new RuntimeException("完成订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 统计订单数量
     */
    @Transactional(readOnly = true)
    public long countByUserId(Long userId) {
        return orderRepository.countByUserId(userId);
    }
    
    /**
     * 统计指定状态的订单数量
     */
    @Transactional(readOnly = true)
    public long countByStatus(OrderStatus status) {
        return orderRepository.countByStatus(status);
    }
    
    /**
     * 统计用户指定状态的订单数量
     */
    @Transactional(readOnly = true)
    public long countByUserIdAndStatus(Long userId, OrderStatus status) {
        return orderRepository.countByUserIdAndStatus(userId, status);
    }
    
    /**
     * 查找用户的最近订单
     */
    @Transactional(readOnly = true)
    public List<Order> findRecentOrdersByUserId(Long userId, Pageable pageable) {
        return orderRepository.findRecentOrdersByUserId(userId, pageable);
    }
    
    /**
     * 查找过期的待支付订单
     */
    @Transactional(readOnly = true)
    public List<Order> findExpiredPendingOrders(int expireMinutes) {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(expireMinutes);
        return orderRepository.findExpiredPendingOrders(expireTime);
    }
    
    /**
     * 自动取消过期订单
     */
    public int autoCancelExpiredOrders(int expireMinutes) {
        try {
            List<Order> expiredOrders = findExpiredPendingOrders(expireMinutes);
            int cancelledCount = 0;
            
            for (Order order : expiredOrders) {
                try {
                    cancelOrder(order.getId(), "系统自动取消：订单超时未支付");
                    cancelledCount++;
                } catch (Exception e) {
                    logger.warn("自动取消订单失败，订单号：{}", order.getOrderNumber(), e);
                }
            }
            
            logger.info("自动取消过期订单完成，取消数量：{}", cancelledCount);
            return cancelledCount;
            
        } catch (Exception e) {
            logger.error("自动取消过期订单失败：", e);
            return 0;
        }
    }
    
    /**
     * 删除订单（软删除，仅管理员可操作）
     */
    public void deleteOrder(Long orderId) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
            
            // 只有已取消或已退款的订单才能删除
            if (order.getStatus() != OrderStatus.CANCELLED && order.getStatus() != OrderStatus.REFUNDED) {
                throw new RuntimeException("只有已取消或已退款的订单才能删除");
            }
            
            orderRepository.delete(order);
            logger.info("订单删除成功，订单号：{}", order.getOrderNumber());
            
        } catch (Exception e) {
            logger.error("删除订单失败：", e);
            throw new RuntimeException("删除订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存订单
     */
    public Order save(Order order) {
        try {
            Order savedOrder = orderRepository.save(order);
            logger.info("订单保存成功，订单ID：{}", savedOrder.getId());
            return savedOrder;
        } catch (Exception e) {
            logger.error("保存订单失败：", e);
            throw new RuntimeException("保存订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存订单项
     */
    public OrderItem saveOrderItem(OrderItem orderItem) {
        try {
            OrderItem savedOrderItem = orderItemRepository.save(orderItem);
            logger.info("订单项保存成功，订单项ID：{}", savedOrderItem.getId());
            return savedOrderItem;
        } catch (Exception e) {
            logger.error("保存订单项失败：", e);
            throw new RuntimeException("保存订单项失败：" + e.getMessage());
        }
    }
    
    /**
     * 分页查找所有订单（支持状态和搜索筛选）
     */
    @Transactional(readOnly = true)
    public Page<Order> findAllOrders(Pageable pageable, OrderStatus status, String search) {
        if (status != null && search != null && !search.trim().isEmpty()) {
            return orderRepository.findByStatusAndOrderNumberContainingIgnoreCase(status, search, pageable);
        } else if (status != null) {
            return orderRepository.findByStatus(status, pageable);
        } else if (search != null && !search.trim().isEmpty()) {
            return orderRepository.findByOrderNumberContainingIgnoreCase(search, pageable);
        } else {
            return orderRepository.findAll(pageable);
        }
    }
    
    /**
     * 分页查找用户的订单（支持状态和搜索筛选）
     */
    @Transactional(readOnly = true)
    public Page<Order> findOrdersByUser(User user, Pageable pageable, OrderStatus status, String search) {
        if (status != null && search != null && !search.trim().isEmpty()) {
            return orderRepository.findByUserAndStatusAndOrderNumberContainingIgnoreCase(user, status, search, pageable);
        } else if (status != null) {
            return orderRepository.findByUserAndStatus(user, status, pageable);
        } else if (search != null && !search.trim().isEmpty()) {
            return orderRepository.findByUserAndOrderNumberContainingIgnoreCase(user, search, pageable);
        } else {
            return orderRepository.findByUser(user, pageable);
        }
    }
    
    /**
     * 获取所有订单统计
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getOrderStats() {
        Map<String, Object> stats = new HashMap<>();
        
        // 总订单数
        long totalOrders = orderRepository.count();
        stats.put("totalOrders", totalOrders);
        
        // 各状态订单数
        stats.put("pendingOrders", orderRepository.countByStatus(OrderStatus.PENDING));
        stats.put("confirmedOrders", orderRepository.countByStatus(OrderStatus.CONFIRMED));
        stats.put("paidOrders", orderRepository.countByStatus(OrderStatus.PAID));
        stats.put("processingOrders", orderRepository.countByStatus(OrderStatus.PROCESSING));
        stats.put("shippedOrders", orderRepository.countByStatus(OrderStatus.SHIPPED));
        stats.put("deliveredOrders", orderRepository.countByStatus(OrderStatus.DELIVERED));
        stats.put("completedOrders", orderRepository.countByStatus(OrderStatus.COMPLETED));
        stats.put("cancelledOrders", orderRepository.countByStatus(OrderStatus.CANCELLED));
        stats.put("refundedOrders", orderRepository.countByStatus(OrderStatus.REFUNDED));
        
        // 今日订单数
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        long todayOrders = orderRepository.countByCreatedAtAfter(today);
        stats.put("todayOrders", todayOrders);
        
        // 总金额
        BigDecimal totalAmount = orderRepository.sumTotalAmountByStatus(OrderStatus.COMPLETED);
        stats.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
        
        return stats;
    }
    
    /**
     * 获取用户订单统计
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getOrderStatsByUser(User user) {
        Map<String, Object> stats = new HashMap<>();
        
        // 用户总订单数
        long totalOrders = orderRepository.countByUser(user);
        stats.put("totalOrders", totalOrders);
        
        // 用户各状态订单数
        stats.put("pendingOrders", orderRepository.countByUserAndStatus(user, OrderStatus.PENDING));
        stats.put("confirmedOrders", orderRepository.countByUserAndStatus(user, OrderStatus.CONFIRMED));
        stats.put("paidOrders", orderRepository.countByUserAndStatus(user, OrderStatus.PAID));
        stats.put("processingOrders", orderRepository.countByUserAndStatus(user, OrderStatus.PROCESSING));
        stats.put("shippedOrders", orderRepository.countByUserAndStatus(user, OrderStatus.SHIPPED));
        stats.put("deliveredOrders", orderRepository.countByUserAndStatus(user, OrderStatus.DELIVERED));
        stats.put("completedOrders", orderRepository.countByUserAndStatus(user, OrderStatus.COMPLETED));
        stats.put("cancelledOrders", orderRepository.countByUserAndStatus(user, OrderStatus.CANCELLED));
        stats.put("refundedOrders", orderRepository.countByUserAndStatus(user, OrderStatus.REFUNDED));
        
        // 用户今日订单数
        LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        long todayOrders = orderRepository.countByUserAndCreatedAtAfter(user, today);
        stats.put("todayOrders", todayOrders);
        
        // 用户总金额
        BigDecimal totalAmount = orderRepository.sumTotalAmountByUserAndStatus(user, OrderStatus.COMPLETED);
        stats.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
        
        return stats;
    }
}
