package com.example.demo.service;

import com.example.demo.model.*;
import com.example.demo.repository.PaymentRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional
public class PaymentService {
    
    private static final Logger logger = LoggerFactory.getLogger(PaymentService.class);
    
    @Autowired
    private PaymentRepository paymentRepository;
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private AlipayService alipayService;
    
    /**
     * 保存支付记录
     */
    public Payment save(Payment payment) {
        try {
            Payment savedPayment = paymentRepository.save(payment);
            logger.info("支付记录保存成功，支付ID：{}", savedPayment.getId());
            return savedPayment;
        } catch (Exception e) {
            logger.error("保存支付记录失败：", e);
            throw new RuntimeException("保存支付记录失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据ID查找支付记录
     */
    @Transactional(readOnly = true)
    public Optional<Payment> findById(Long id) {
        return paymentRepository.findById(id);
    }
    
    /**
     * 根据订单ID查找支付记录
     */
    @Transactional(readOnly = true)
    public Optional<Payment> findByOrderId(String orderId) {
        return paymentRepository.findByOrderId(orderId);
    }
    
    /**
     * 根据外部交易ID查找支付记录
     */
    @Transactional(readOnly = true)
    public Optional<Payment> findByExternalTransactionId(String externalTransactionId) {
        return paymentRepository.findByExternalTransactionId(externalTransactionId);
    }
    
    /**
     * 根据用户ID查找支付记录
     */
    @Transactional(readOnly = true)
    public List<Payment> findByUserId(Long userId) {
        return paymentRepository.findByUserIdOrderByCreatedAtDesc(userId);
    }
    
    /**
     * 查找所有支付记录
     */
    @Transactional(readOnly = true)
    public List<Payment> findAll() {
        return paymentRepository.findAll();
    }
    
    /**
     * 根据状态查找支付记录
     */
    @Transactional(readOnly = true)
    public List<Payment> findByStatus(PaymentStatus status) {
        return paymentRepository.findByStatus(status);
    }
    
    /**
     * 更新支付状态
     */
    public Payment updatePaymentStatus(Long paymentId, PaymentStatus newStatus) {
        try {
            Payment payment = paymentRepository.findById(paymentId)
                    .orElseThrow(() -> new RuntimeException("支付记录不存在：" + paymentId));
            
            PaymentStatus oldStatus = payment.getStatus();
            payment.setStatus(newStatus);
            
            if (newStatus == PaymentStatus.SUCCESS) {
                payment.setPaidAt(LocalDateTime.now());
                
                // 更新关联订单状态
                if (payment.getOrder() != null) {
                    orderService.confirmPayment(payment.getOrder().getId(), payment.getExternalTransactionId());
                }
            }
            
            Payment updatedPayment = paymentRepository.save(payment);
            logger.info("支付状态更新成功，支付ID：{}，状态：{} -> {}", 
                paymentId, oldStatus, newStatus);
            
            return updatedPayment;
            
        } catch (Exception e) {
            logger.error("更新支付状态失败：", e);
            throw new RuntimeException("更新支付状态失败：" + e.getMessage());
        }
    }
    
    /**
     * 确认支付成功
     */
    public Payment confirmPaymentSuccess(Long paymentId, String externalTransactionId) {
        try {
            Payment payment = paymentRepository.findById(paymentId)
                    .orElseThrow(() -> new RuntimeException("支付记录不存在：" + paymentId));
            
            payment.setStatus(PaymentStatus.SUCCESS);
            payment.setPaidAt(LocalDateTime.now());
            payment.setExternalTransactionId(externalTransactionId);
            
            Payment confirmedPayment = paymentRepository.save(payment);
            
            // 更新关联订单状态
            if (payment.getOrder() != null) {
                orderService.confirmPayment(payment.getOrder().getId(), externalTransactionId);
            } else {
                // 如果没有关联订单，自动创建一个订单
                createOrderFromPayment(confirmedPayment);
            }
            
            // 根据支付金额增加积分
            addPointsForPayment(confirmedPayment);
            
            logger.info("支付确认成功，支付ID：{}，外部交易ID：{}", paymentId, externalTransactionId);
            return confirmedPayment;
            
        } catch (Exception e) {
            logger.error("确认支付成功失败：", e);
            throw new RuntimeException("确认支付成功失败：" + e.getMessage());
        }
    }
    
    /**
     * 确认支付失败
     */
    public Payment confirmPaymentFailure(Long paymentId, String failureReason) {
        try {
            Payment payment = paymentRepository.findById(paymentId)
                    .orElseThrow(() -> new RuntimeException("支付记录不存在：" + paymentId));
            
            payment.setStatus(PaymentStatus.FAILED);
            if (failureReason != null && !failureReason.isEmpty()) {
                payment.setDescription((payment.getDescription() != null ? payment.getDescription() + "\n" : "") + 
                    "失败原因：" + failureReason);
            }
            
            Payment failedPayment = paymentRepository.save(payment);
            logger.info("支付确认失败，支付ID：{}，失败原因：{}", paymentId, failureReason);
            
            return failedPayment;
            
        } catch (Exception e) {
            logger.error("确认支付失败失败：", e);
            throw new RuntimeException("确认支付失败失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建订单支付
     */
    public Payment createOrderPayment(Order order, PaymentMethod paymentMethod) {
        try {
            Payment payment = new Payment();
            payment.setOrderId(order.getOrderNumber());
            payment.setAmount(order.getTotalAmount());
            payment.setCurrency(order.getCurrency());
            payment.setPaymentMethod(paymentMethod);
            payment.setDescription("订单支付 - " + order.getOrderNumber());
            payment.setUser(order.getUser());
            payment.setOrder(order);
            payment.setStatus(PaymentStatus.PENDING);
            
            Payment savedPayment = paymentRepository.save(payment);
            logger.info("订单支付创建成功，订单号：{}，支付ID：{}", order.getOrderNumber(), savedPayment.getId());
            
            return savedPayment;
            
        } catch (Exception e) {
            logger.error("创建订单支付失败：", e);
            throw new RuntimeException("创建订单支付失败：" + e.getMessage());
        }
    }
    
    /**
     * 统计支付记录数量
     */
    @Transactional(readOnly = true)
    public long countByUserId(Long userId) {
        return paymentRepository.countByUserId(userId);
    }
    
    /**
     * 统计指定状态的支付记录数量
     */
    @Transactional(readOnly = true)
    public long countByStatus(PaymentStatus status) {
        return paymentRepository.countByStatus(status);
    }
    
    /**
     * 统计用户指定状态的支付记录数量
     */
    @Transactional(readOnly = true)
    public long countByUserIdAndStatus(Long userId, PaymentStatus status) {
        return paymentRepository.countByUserIdAndStatus(userId, status);
    }
    
    /**
     * 删除支付记录
     */
    public void deletePayment(Long paymentId) {
        try {
            Payment payment = paymentRepository.findById(paymentId)
                    .orElseThrow(() -> new RuntimeException("支付记录不存在：" + paymentId));
            
            // 只有失败的支付记录才能删除
            if (payment.getStatus() != PaymentStatus.FAILED) {
                throw new RuntimeException("只有失败的支付记录才能删除");
            }
            
            paymentRepository.delete(payment);
            logger.info("支付记录删除成功，支付ID：{}", paymentId);
            
        } catch (Exception e) {
            logger.error("删除支付记录失败：", e);
            throw new RuntimeException("删除支付记录失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据用户名查找支付记录
     */
    @Transactional(readOnly = true)
    public List<Payment> findByUsername(String username) {
        try {
            logger.info("PaymentService: 开始查找用户 {} 的支付记录", username);
            
            // 先查找用户
            User user = userService.findByUsername(username);
            if (user == null) {
                logger.error("PaymentService: 用户 {} 不存在", username);
                throw new RuntimeException("用户不存在: " + username);
            }
            
            logger.info("PaymentService: 找到用户 {}, ID: {}", username, user.getId());
            
            // 查找支付记录
            List<Payment> payments = paymentRepository.findByUserIdOrderByCreatedAtDesc(user.getId());
            logger.info("PaymentService: 用户 {} 的支付记录数量: {}", username, payments.size());
            
            return payments;
        } catch (Exception e) {
            logger.error("PaymentService: 根据用户名查找支付记录失败，用户名: {}, 错误: {}", username, e.getMessage(), e);
            throw new RuntimeException("查找支付记录失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建支付
     */
    public Payment createPayment(String username, String orderId, String amountStr, String method) {
        try {
            logger.info("创建支付 - 用户名: {}, 订单ID: {}, 金额: {}, 支付方式: {}", username, orderId, amountStr, method);
            
            User user = userService.findByUsername(username);
            if (user == null) {
                logger.error("用户不存在: {}", username);
                // 如果是匿名用户，创建一个临时用户记录
                if (username.startsWith("anonymous_")) {
                    user = createAnonymousUser(username);
                } else {
                    throw new RuntimeException("用户不存在: " + username);
                }
            }
            
            logger.info("找到用户: {}", user.getUsername());
            
            BigDecimal amount = new BigDecimal(amountStr);
            PaymentMethod paymentMethod = PaymentMethod.valueOf(method);
            
            logger.info("金额: {}, 支付方式: {}", amount, paymentMethod);
            
            Payment payment = new Payment();
            payment.setUser(user);
            payment.setOrderId(orderId);
            payment.setAmount(amount);
            payment.setPaymentMethod(paymentMethod);
            payment.setStatus(PaymentStatus.PENDING);
            payment.setCreatedAt(LocalDateTime.now());
            
            Payment savedPayment = save(payment);
            logger.info("支付记录创建成功: {}", savedPayment.getId());
            
            // 根据支付方式调用相应的支付服务
            if (paymentMethod == PaymentMethod.ALIPAY) {
                try {
                    String paymentUrl = alipayService.createPayment(savedPayment);
                    savedPayment.setPaymentUrl(paymentUrl);
                    save(savedPayment);
                    logger.info("支付宝支付URL生成成功: {}", paymentUrl);
                } catch (Exception e) {
                    logger.error("调用支付宝支付接口失败：", e);
                    // 不抛出异常，让前端处理
                }
            }
            
            return savedPayment;
        } catch (Exception e) {
            logger.error("创建支付失败：", e);
            throw new RuntimeException("创建支付失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建匿名用户
     */
    private User createAnonymousUser(String username) {
        try {
            User user = new User();
            user.setUsername(username);
            user.setEmail(username + "@anonymous.com");
            user.setPasswordHash("anonymous");
            user.setRole("ROLE_USER");
            
            return userService.save(user);
        } catch (Exception e) {
            logger.error("创建匿名用户失败：", e);
            throw new RuntimeException("创建匿名用户失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取用户支付统计
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getUserPaymentStats(String username) {
        try {
            User user = userService.findByUsername(username);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            Long userId = user.getId();
            
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalPayments", paymentRepository.countByUserId(userId));
            stats.put("successfulPayments", paymentRepository.countByUserIdAndStatus(userId, PaymentStatus.SUCCESS));
            stats.put("pendingPayments", paymentRepository.countByUserIdAndStatus(userId, PaymentStatus.PENDING));
            stats.put("failedPayments", paymentRepository.countByUserIdAndStatus(userId, PaymentStatus.FAILED));
            stats.put("cancelledPayments", paymentRepository.countByUserIdAndStatus(userId, PaymentStatus.CANCELLED));
            
            return stats;
        } catch (Exception e) {
            logger.error("获取用户支付统计失败：", e);
            throw new RuntimeException("获取支付统计失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据支付金额增加积分
     */
    private void addPointsForPayment(Payment payment) {
        try {
            BigDecimal amount = payment.getAmount();
            Integer pointsToAdd = 0;
            
            // 根据支付金额确定积分奖励
            if (amount.compareTo(new BigDecimal("59.00")) >= 0 && amount.compareTo(new BigDecimal("259.00")) < 0) {
                // 标准版订阅 (59-258元) - 200积分
                pointsToAdd = 200;
            } else if (amount.compareTo(new BigDecimal("259.00")) >= 0) {
                // 专业版订阅 (259元以上) - 1000积分
                pointsToAdd = 1000;
            }
            
            if (pointsToAdd > 0) {
                userService.addPoints(payment.getUser().getId(), pointsToAdd);
                logger.info("用户 {} 支付 {} 元，获得 {} 积分", 
                    payment.getUser().getUsername(), amount, pointsToAdd);
            }
            
        } catch (Exception e) {
            logger.error("增加积分失败：", e);
            // 不抛出异常，避免影响支付流程
        }
    }
    
    /**
     * 从支付记录自动创建订单
     */
    private void createOrderFromPayment(Payment payment) {
        try {
            // 生成订单号
            String orderNumber = "ORD" + System.currentTimeMillis();
            
            // 创建订单
            Order order = new Order();
            order.setUser(payment.getUser());
            order.setOrderNumber(orderNumber);
            order.setTotalAmount(payment.getAmount());
            order.setCurrency("CNY");
            order.setStatus(OrderStatus.PAID); // 支付成功，订单状态为已支付
            order.setOrderType(OrderType.PAYMENT); // 订单类型为支付订单
            order.setCreatedAt(LocalDateTime.now());
            order.setUpdatedAt(LocalDateTime.now());
            
            // 保存订单
            Order savedOrder = orderService.save(order);
            
            // 创建订单项
            OrderItem orderItem = new OrderItem();
            orderItem.setOrder(savedOrder);
            orderItem.setProductName("支付服务 - " + payment.getPaymentMethod().name());
            orderItem.setProductDescription("通过" + payment.getPaymentMethod().name() + "完成的支付服务");
            orderItem.setQuantity(1);
            orderItem.setUnitPrice(payment.getAmount());
            orderItem.setSubtotal(payment.getAmount());
            
            // 保存订单项
            orderService.saveOrderItem(orderItem);
            
            // 更新支付记录，关联到新创建的订单
            payment.setOrder(savedOrder);
            paymentRepository.save(payment);
            
            logger.info("从支付记录自动创建订单成功，支付ID：{}，订单ID：{}，订单号：{}", 
                       payment.getId(), savedOrder.getId(), orderNumber);
            
        } catch (Exception e) {
            logger.error("从支付记录创建订单失败：", e);
            throw new RuntimeException("创建订单失败：" + e.getMessage());
        }
    }
}
