package com.snack.server.module.cart.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.snack.server.common.ResultCode;
import com.snack.server.exception.BusinessException;
import com.snack.server.module.cart.dto.req.CartAddReq;
import com.snack.server.module.cart.dto.req.CartUpdateReq;
import com.snack.server.module.cart.entity.Cart;
import com.snack.server.module.cart.mapper.CartMapper;
import com.snack.server.module.cart.service.CartService;
import com.snack.server.module.cart.vo.CartItemVO;
import com.snack.server.module.cart.vo.CartVO;
import com.snack.server.module.product.entity.Product;
import com.snack.server.module.product.entity.ProductSku;
import com.snack.server.module.product.mapper.ProductMapper;
import com.snack.server.module.product.mapper.ProductSkuMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 购物车业务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CartServiceImpl implements CartService {

    /** 购物车单 SKU 数量上限（防止恶意刷单） */
    private static final int MAX_QTY_PER_ITEM = 99;

    private final CartMapper cartMapper;
    private final ProductMapper productMapper;
    private final ProductSkuMapper productSkuMapper;

    // ==================== 查询 ====================

    @Override
    public CartVO getCurrentCart() {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Cart> carts = cartMapper.selectList(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .orderByDesc(Cart::getId)
        );
        if (CollUtil.isEmpty(carts)) {
            return emptyCart();
        }
        return enrichCartVO(carts);
    }

    private CartVO emptyCart() {
        CartVO vo = new CartVO();
        vo.setItems(new ArrayList<>());
        vo.setTotalCount(0);
        vo.setSelectedCount(0);
        vo.setTotalAmount(BigDecimal.ZERO);
        vo.setSelectedAmount(BigDecimal.ZERO);
        vo.setAllSelected(0);
        return vo;
    }

    /**
     * 装配购物车 VO（含商品 / SKU 信息）
     */
    private CartVO enrichCartVO(List<Cart> carts) {
        // 1. 批量查 SPU / SKU
        Set<Long> productIds = carts.stream().map(Cart::getProductId).collect(Collectors.toSet());
        Set<Long> skuIds = carts.stream().map(Cart::getSkuId).collect(Collectors.toSet());

        Map<Long, Product> productMap = productMapper.selectByIds(productIds).stream()
                .collect(Collectors.toMap(Product::getId, p -> p));
        Map<Long, ProductSku> skuMap = productSkuMapper.selectByIds(skuIds).stream()
                .collect(Collectors.toMap(ProductSku::getId, s -> s));

        // 2. 转 VO + 统计
        int totalCount = 0;
        int selectedCount = 0;
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal selectedAmount = BigDecimal.ZERO;
        int allSelected = 1;

        List<CartItemVO> items = new ArrayList<>();
        for (Cart c : carts) {
            Product p = productMap.get(c.getProductId());
            ProductSku s = skuMap.get(c.getSkuId());
            if (p == null || s == null) {
                // 商品 / SKU 已被删除，跳过（或保留用于用户清理）
                continue;
            }
            CartItemVO vo = new CartItemVO();
            vo.setId(c.getId());
            vo.setProductId(p.getId());
            vo.setProductName(p.getName());
            vo.setProductImage(StrUtil.blankToDefault(p.getMainImage(), s.getImage()));
            vo.setSkuId(s.getId());
            vo.setSkuName(s.getSkuName());
            vo.setSkuImage(s.getImage());
            vo.setPrice(s.getPrice());
            vo.setQuantity(c.getQuantity());
            vo.setSubtotal(s.getPrice().multiply(BigDecimal.valueOf(c.getQuantity())));
            vo.setStock(s.getStock());
            vo.setSelected(c.getSelected());
            vo.setProductStatus(p.getStatus());
            items.add(vo);

            totalCount += c.getQuantity();
            totalAmount = totalAmount.add(vo.getSubtotal());
            if (c.getSelected() != null && c.getSelected() == 1) {
                selectedCount += c.getQuantity();
                selectedAmount = selectedAmount.add(vo.getSubtotal());
            } else {
                allSelected = 0;
            }
        }

        // 如果购物车里没有未选中的项，才算全选
        if (items.stream().anyMatch(i -> i.getSelected() == 0)) {
            allSelected = 0;
        }

        CartVO vo = new CartVO();
        vo.setItems(items);
        vo.setTotalCount(totalCount);
        vo.setSelectedCount(selectedCount);
        vo.setTotalAmount(totalAmount);
        vo.setSelectedAmount(selectedAmount);
        vo.setAllSelected(allSelected);
        return vo;
    }

    // ==================== 添加 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addItem(CartAddReq req) {
        Long userId = StpUtil.getLoginIdAsLong();

        // 1. 校验商品
        Product product = productMapper.selectById(req.getProductId());
        if (product == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        if (product.getStatus() == null || product.getStatus() == 0) {
            throw new BusinessException(ResultCode.PRODUCT_OFF_SHELF);
        }
        ProductSku sku = productSkuMapper.selectById(req.getSkuId());
        if (sku == null || !sku.getProductId().equals(req.getProductId())) {
            throw new BusinessException(1000, "SKU 不存在或与商品不匹配");
        }
        if (sku.getStock() == null || sku.getStock() < req.getQuantity()) {
            throw new BusinessException(ResultCode.STOCK_INSUFFICIENT);
        }

        // 2. 已存在则累加
        Cart existing = cartMapper.selectOne(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSkuId, req.getSkuId())
        );

        if (existing != null) {
            int newQty = existing.getQuantity() + req.getQuantity();
            if (newQty > MAX_QTY_PER_ITEM) {
                throw new BusinessException(1000, "单 SKU 数量不能超过 " + MAX_QTY_PER_ITEM);
            }
            if (newQty > sku.getStock()) {
                throw new BusinessException(ResultCode.STOCK_INSUFFICIENT);
            }
            cartMapper.updateQuantity(userId, req.getSkuId(), newQty);
            log.info("用户 {} 累加购物车 skuId={} -> {}", userId, req.getSkuId(), newQty);
        } else {
            if (req.getQuantity() > MAX_QTY_PER_ITEM) {
                throw new BusinessException(1000, "单 SKU 数量不能超过 " + MAX_QTY_PER_ITEM);
            }
            Cart cart = new Cart();
            cart.setUserId(userId);
            cart.setProductId(req.getProductId());
            cart.setSkuId(req.getSkuId());
            cart.setQuantity(req.getQuantity());
            cart.setSelected(1); // 新加入默认选中
            cartMapper.insert(cart);
            log.info("用户 {} 加入购物车 skuId={} qty={}", userId, req.getSkuId(), req.getQuantity());
        }
    }

    // ==================== 修改数量 ====================

    @Override
    public void updateQuantity(CartUpdateReq req) {
        Long userId = StpUtil.getLoginIdAsLong();
        Cart existing = cartMapper.selectOne(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSkuId, req.getSkuId())
        );
        if (existing == null) {
            throw new BusinessException(1000, "购物车中不存在该商品");
        }
        if (req.getQuantity() > MAX_QTY_PER_ITEM) {
            throw new BusinessException(1000, "单 SKU 数量不能超过 " + MAX_QTY_PER_ITEM);
        }
        // 校验库存
        ProductSku sku = productSkuMapper.selectById(req.getSkuId());
        if (sku != null && sku.getStock() != null && req.getQuantity() > sku.getStock()) {
            throw new BusinessException(ResultCode.STOCK_INSUFFICIENT);
        }
        cartMapper.updateQuantity(userId, req.getSkuId(), req.getQuantity());
    }

    // ==================== 选中状态 ====================

    @Override
    public void updateSelected(Long skuId, Integer selected) {
        Long userId = StpUtil.getLoginIdAsLong();
        Cart existing = cartMapper.selectOne(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSkuId, skuId)
        );
        if (existing == null) {
            throw new BusinessException(1000, "购物车中不存在该商品");
        }
        if (existing.getSelected() != null && existing.getSelected().equals(selected)) {
            return;
        }
        existing.setSelected(selected);
        cartMapper.updateById(existing);
    }

    @Override
    public void updateAllSelected(Integer selected) {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Cart> carts = cartMapper.selectList(
                new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, userId)
        );
        for (Cart c : carts) {
            c.setSelected(selected);
            cartMapper.updateById(c);
        }
    }

    // ==================== 删除 ====================

    @Override
    public void deleteItem(Long skuId) {
        Long userId = StpUtil.getLoginIdAsLong();
        cartMapper.delete(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSkuId, skuId)
        );
    }

    @Override
    public void deleteItems(Collection<Long> skuIds) {
        if (CollUtil.isEmpty(skuIds)) return;
        Long userId = StpUtil.getLoginIdAsLong();
        cartMapper.delete(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .in(Cart::getSkuId, skuIds)
        );
    }

    @Override
    public void clear() {
        Long userId = StpUtil.getLoginIdAsLong();
        cartMapper.delete(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, userId));
    }

    // ==================== 内部 ====================

    @Override
    public List<Cart> listSelectedItems() {
        Long userId = StpUtil.getLoginIdAsLong();
        return cartMapper.selectList(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSelected, 1)
        );
    }

    @Override
    public void deleteSelectedItems() {
        Long userId = StpUtil.getLoginIdAsLong();
        cartMapper.delete(
                new LambdaQueryWrapper<Cart>()
                        .eq(Cart::getUserId, userId)
                        .eq(Cart::getSelected, 1)
        );
    }

    @Override
    public int countByUserId(Long userId) {
        return cartMapper.selectCount(
                new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, userId)
        ).intValue();
    }
}
