package com.smyhub.store.mengyastorebackendjava.service;

import com.smyhub.store.mengyastorebackendjava.dto.request.CheckoutRequest;
import com.smyhub.store.mengyastorebackendjava.dto.response.OrderResponse;
import com.smyhub.store.mengyastorebackendjava.entity.Order;
import com.smyhub.store.mengyastorebackendjava.entity.Product;
import com.smyhub.store.mengyastorebackendjava.exception.BusinessException;
import com.smyhub.store.mengyastorebackendjava.mq.OrderEmailPayload;
import com.smyhub.store.mengyastorebackendjava.mq.OrderEmailProducer;
import com.smyhub.store.mengyastorebackendjava.repository.OrderRepository;
import com.smyhub.store.mengyastorebackendjava.security.SproutGateUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final ProductService productService;
    private final SiteService siteService;
    private final EmailService emailService;
    private final OrderEmailProducer orderEmailProducer;

    @Transactional
    public CheckoutResult checkout(CheckoutRequest req, SproutGateUser optionalUser) {
        String userAccount = optionalUser != null ? optionalUser.getAccount() : "";
        String userName = optionalUser != null ? optionalUser.getUsername() : "";
        String userEmail = optionalUser != null ? optionalUser.getEmail() : "";

        int qty = req.getQuantity() <= 0 ? 1 : req.getQuantity();
        Product product = productService.findById(req.getProductId().strip());

        if (!product.isActive()) {
            throw new BusinessException("商品暂时无法购买");
        }
        if (product.isRequireLogin() && !StringUtils.hasText(userAccount)) {
            throw new BusinessException("该商品需要登录后才能购买", HttpStatus.UNAUTHORIZED);
        }
        if (product.getMaxPerAccount() > 0 && StringUtils.hasText(userAccount)) {
            int purchased = orderRepository.sumQuantityByUserAccountAndProductId(userAccount, product.getId());
            if (purchased + qty > product.getMaxPerAccount()) {
                int remain = product.getMaxPerAccount() - purchased;
                if (remain <= 0) {
                    throw new BusinessException(String.format("每个账户最多购买 %d 个，您已达上限", product.getMaxPerAccount()));
                }
                throw new BusinessException(String.format("每个账户最多购买 %d 个，您还可购买 %d 个", product.getMaxPerAccount(), remain));
            }
        }

        List<String> deliveredCodes;
        boolean isFixed = "fixed".equalsIgnoreCase(product.getFulfillmentType());
        if (isFixed) {
            String content = product.getFixedContent() != null ? product.getFixedContent().strip() : "";
            if (content.isEmpty()) {
                throw new BusinessException("该商品为固定内容发货，但未配置发货内容，请联系管理员");
            }
            deliveredCodes = Collections.nCopies(qty, content);
        } else {
            deliveredCodes = productService.popCodes(product.getId(), qty);
        }

        String notifyEmail = StringUtils.hasText(userEmail) ? userEmail
                : StringUtils.hasText(req.getNotifyEmail()) ? req.getNotifyEmail().strip()
                : StringUtils.hasText(req.getContactEmail()) ? req.getContactEmail().strip()
                : "";

        Order order = new Order();
        order.setId(UUID.randomUUID().toString());
        order.setProductId(product.getId());
        order.setProductName(product.getName());
        order.setUserAccount(userAccount);
        order.setUserName(userName);
        order.setQuantity(qty);
        order.setDeliveredCodes(new ArrayList<>(deliveredCodes));
        order.setStatus("completed");
        order.setDeliveryMode("auto");
        order.setNote(req.getNote() != null ? req.getNote().strip() : "");
        order.setContactPhone(req.getContactPhone() != null ? req.getContactPhone().strip() : "");
        order.setContactEmail(req.getContactEmail() != null ? req.getContactEmail().strip() : "");
        order.setNotifyEmail(notifyEmail);
        order.setCreatedAt(LocalDateTime.now());
        orderRepository.save(order);

        productService.incrementSold(product.getId(), qty);

        if (StringUtils.hasText(notifyEmail)) {
            sendOrderEmail(notifyEmail, userName, product.getName(), order.getId(), qty, new ArrayList<>(deliveredCodes), false);
        }

        return new CheckoutResult(
                order.getId(),
                product.getId(),
                qty,
                product.getViewCount(),
                order.getStatus(),
                new ArrayList<>(deliveredCodes),
                order.getDeliveryMode());
    }

    public OrderResponse confirmOrder(String orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new BusinessException("订单不存在", HttpStatus.NOT_FOUND));
        order.setStatus("confirmed");
        orderRepository.save(order);

        boolean isManual = "manual".equals(order.getDeliveryMode());
        if (isManual) {
            String email = StringUtils.hasText(order.getNotifyEmail())
                    ? order.getNotifyEmail() : order.getContactEmail();
            if (StringUtils.hasText(email)) {
                sendOrderEmail(email, order.getUserName(), order.getProductName(),
                        order.getId(), order.getQuantity(), order.getDeliveredCodes(), false);
            }
        }
        return toResponse(order);
    }

    public List<OrderResponse> getMyOrders(String userAccount) {
        return orderRepository.findByUserAccountOrderByCreatedAtDesc(userAccount)
                .stream().map(this::toResponse).toList();
    }

    public List<OrderResponse> listAllOrders() {
        return orderRepository.findAllByOrderByCreatedAtDesc()
                .stream().map(this::toResponse).toList();
    }

    @Transactional
    public void deleteOrder(String orderId) {
        if (!orderRepository.existsById(orderId)) {
            throw new BusinessException("订单不存在", HttpStatus.NOT_FOUND);
        }
        orderRepository.deleteById(orderId);
    }

    private void sendOrderEmail(String toEmail, String toName, String productName,
                                String orderId, int qty, List<String> codes, boolean isManual) {
        SiteService.SmtpConfig cfg = siteService.getSmtpConfig();
        if (!cfg.isConfigured()) return;

        OrderEmailPayload payload = new OrderEmailPayload(toEmail, toName, productName, orderId, qty, codes, isManual);
        boolean queued = orderEmailProducer.publish(payload);
        if (!queued) {
            EmailService.OrderNotifyData data = new EmailService.OrderNotifyData();
            data.toEmail = toEmail;
            data.toName = toName;
            data.productName = productName;
            data.orderId = orderId;
            data.quantity = qty;
            data.codes = codes;
            data.isManual = isManual;
            Thread emailThread = new Thread(() -> emailService.sendOrderNotify(cfg, data));
            emailThread.setDaemon(true);
            emailThread.start();
        }
    }

    private OrderResponse toResponse(Order o) {
        return OrderResponse.builder()
                .id(o.getId())
                .productId(o.getProductId())
                .productName(o.getProductName())
                .userAccount(o.getUserAccount())
                .userName(o.getUserName())
                .quantity(o.getQuantity())
                .deliveredCodes(o.getDeliveredCodes())
                .status(o.getStatus())
                .deliveryMode(o.getDeliveryMode())
                .note(o.getNote())
                .contactPhone(o.getContactPhone())
                .contactEmail(o.getContactEmail())
                .notifyEmail(o.getNotifyEmail())
                .createdAt(o.getCreatedAt())
                .build();
    }

    public record CheckoutResult(
            String orderId,
            String productId,
            int qty,
            int viewCount,
            String status,
            java.util.List<String> deliveredCodes,
            String deliveryMode) {
    }
}
