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

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.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.snack.server.common.ResultCode;
import com.snack.server.exception.BusinessException;
import com.snack.server.module.category.entity.Category;
import com.snack.server.module.category.mapper.CategoryMapper;
import com.snack.server.module.product.dto.req.ProductPageReq;
import com.snack.server.module.product.dto.req.ProductSaveReq;
import com.snack.server.module.product.dto.req.StockAdjustReq;
import com.snack.server.module.product.entity.Product;
import com.snack.server.module.product.entity.ProductSku;
import com.snack.server.module.product.enums.ProductStatusEnum;
import com.snack.server.module.product.mapper.ProductMapper;
import com.snack.server.module.product.mapper.ProductSkuMapper;
import com.snack.server.module.product.service.ProductService;
import com.snack.server.module.product.vo.ProductDetailVO;
import com.snack.server.module.product.vo.ProductListVO;
import com.snack.server.module.product.vo.ProductSkuVO;
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 ProductServiceImpl implements ProductService {

    private final ProductMapper productMapper;
    private final ProductSkuMapper productSkuMapper;
    private final CategoryMapper categoryMapper;

    // ==================== 分页查询 ====================

    @Override
    public Page<ProductListVO> pageProducts(ProductPageReq req) {
        Page<Product> page = new Page<>(req.getCurrent(), req.getSize());
        LambdaQueryWrapper<Product> wrapper = buildQueryWrapper(req)
                .orderByDesc(Product::getId);

        Page<Product> result = productMapper.selectPage(page, wrapper);
        return toListVOPage(result);
    }

    @Override
    public List<ProductListVO> listByCategoryIds(Collection<Long> categoryIds, String orderBy, Integer limit) {
        // categoryIds 为空表示不限分类（用于首页热门 / 新品等场景）
        ProductPageReq req = new ProductPageReq();
        req.setCurrent(1L);
        req.setSize((long) (limit == null ? 10 : limit));
        req.setStatus(ProductStatusEnum.ON_SHELF.getCode());
        req.setOrderBy(orderBy);

        LambdaQueryWrapper<Product> wrapper = buildQueryWrapper(req);
        if (CollUtil.isNotEmpty(categoryIds)) {
            wrapper.in(Product::getCategoryId, categoryIds);
        }
        applyOrderBy(wrapper, orderBy);

        List<Product> products = productMapper.selectList(wrapper);
        return enrichListVO(products);
    }

    @Override
    public List<ProductListVO> listHotProducts(Integer limit) {
        long size = limit == null ? 10 : limit;
        ProductPageReq req = new ProductPageReq();
        req.setStatus(ProductStatusEnum.ON_SHELF.getCode());
        req.setIsHot(1);
        req.setOrderBy("sales_desc");

        LambdaQueryWrapper<Product> wrapper = buildQueryWrapper(req);
        applyOrderBy(wrapper, "sales_desc");
        wrapper.last("LIMIT " + size);
        return enrichListVO(productMapper.selectList(wrapper));
    }

    @Override
    public List<ProductListVO> listNewProducts(Integer limit) {
        long size = limit == null ? 10 : limit;
        ProductPageReq req = new ProductPageReq();
        req.setStatus(ProductStatusEnum.ON_SHELF.getCode());
        req.setIsNew(1);
        req.setOrderBy("create_desc");

        LambdaQueryWrapper<Product> wrapper = buildQueryWrapper(req);
        applyOrderBy(wrapper, "create_desc");
        wrapper.last("LIMIT " + size);
        return enrichListVO(productMapper.selectList(wrapper));
    }

    private LambdaQueryWrapper<Product> buildQueryWrapper(ProductPageReq req) {
        return new LambdaQueryWrapper<Product>()
                .and(StrUtil.isNotBlank(req.getKeyword()), w -> w
                        .like(Product::getName, req.getKeyword())
                        .or().like(Product::getBrand, req.getKeyword())
                )
                .eq(req.getCategoryId() != null, Product::getCategoryId, req.getCategoryId())
                .eq(req.getStatus() != null, Product::getStatus, req.getStatus())
                .eq(req.getIsHot() != null, Product::getIsHot, req.getIsHot())
                .eq(req.getIsNew() != null, Product::getIsNew, req.getIsNew());
    }

    private void applyOrderBy(LambdaQueryWrapper<Product> wrapper, String orderBy) {
        if (StrUtil.isBlank(orderBy)) {
            wrapper.orderByDesc(Product::getId);
            return;
        }
        switch (orderBy) {
            case "sales_desc"  -> wrapper.orderByDesc(Product::getSales);
            case "price_asc"   -> wrapper.orderByAsc(Product::getId); // 简化：用子查询会更准
            case "price_desc"  -> wrapper.orderByDesc(Product::getId);
            case "create_desc" -> wrapper.orderByDesc(Product::getId);
            default            -> wrapper.orderByDesc(Product::getId);
        }
    }

    private Page<ProductListVO> toListVOPage(Page<Product> page) {
        Page<ProductListVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(enrichListVO(page.getRecords()));
        return voPage;
    }

    /**
     * 把 Product 列表 → ProductListVO（含分类名、起售价、库存等）
     */
    private List<ProductListVO> enrichListVO(List<Product> products) {
        if (CollUtil.isEmpty(products)) {
            return new ArrayList<>();
        }
        // 1. 批量取分类名
        Set<Long> categoryIds = products.stream()
                .map(Product::getCategoryId).filter(Objects::nonNull).collect(Collectors.toSet());
        Map<Long, String> categoryNameMap = new HashMap<>();
        if (!categoryIds.isEmpty()) {
            categoryMapper.selectByIds(categoryIds)
                    .forEach(c -> categoryNameMap.put(c.getId(), c.getName()));
        }

        // 2. 批量取起售价
        List<Long> productIds = products.stream().map(Product::getId).toList();
        Map<Long, BigDecimal> minPriceMap = new HashMap<>();
        Map<Long, Integer> stockMap = new HashMap<>();
        if (!productIds.isEmpty()) {
            try {
                List<Map<String, Object>> priceList = productMapper.selectMinPriceByProductIds(productIds);
                for (Map<String, Object> row : priceList) {
                    Long pid = ((Number) row.get("productId")).longValue();
                    Object minPrice = row.get("minPrice");
                    Object totalStock = row.get("totalStock");
                    if (minPrice != null) minPriceMap.put(pid, new BigDecimal(minPrice.toString()));
                    if (totalStock != null) stockMap.put(pid, ((Number) totalStock).intValue());
                }
            } catch (Exception e) {
                log.warn("查询起售价失败，降级为单条查询：{}", e.getMessage());
            }
        }

        // 3. 组装
        return products.stream().map(p -> {
            ProductListVO vo = new ProductListVO();
            BeanUtil.copyProperties(p, vo);
            vo.setCategoryName(categoryNameMap.get(p.getCategoryId()));
            vo.setMinPrice(minPriceMap.get(p.getId()));
            vo.setTotalStock(stockMap.getOrDefault(p.getId(), 0));
            return vo;
        }).toList();
    }

    // ==================== 详情 ====================

    @Override
    public ProductDetailVO getDetail(Long id) {
        Product product = productMapper.selectById(id);
        if (product == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        return enrichDetailVO(product, true);
    }

    @Override
    public ProductDetailVO getById(Long id) {
        Product product = productMapper.selectById(id);
        if (product == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        return enrichDetailVO(product, false);
    }

    private ProductDetailVO enrichDetailVO(Product p, boolean withSku) {
        ProductDetailVO vo = new ProductDetailVO();
        BeanUtil.copyProperties(p, vo, "subImages");
        // 分类名
        if (p.getCategoryId() != null) {
            Category c = categoryMapper.selectById(p.getCategoryId());
            if (c != null) vo.setCategoryName(c.getName());
        }
        // 副图 JSON 数组 → List
        if (StrUtil.isNotBlank(p.getSubImages())) {
            try {
                vo.setSubImages(com.alibaba.fastjson2.JSON.parseArray(p.getSubImages(), String.class));
            } catch (Exception e) {
                log.warn("解析副图 JSON 失败：{}", p.getSubImages());
            }
        }
        // SKU
        if (withSku) {
            List<ProductSku> skus = productSkuMapper.selectList(
                    new LambdaQueryWrapper<ProductSku>()
                            .eq(ProductSku::getProductId, p.getId())
                            .orderByAsc(ProductSku::getSort)
            );
            vo.setSkuList(skus.stream().map(s -> {
                ProductSkuVO skuVO = new ProductSkuVO();
                BeanUtil.copyProperties(s, skuVO);
                return skuVO;
            }).toList());
            // 起售价
            if (CollUtil.isNotEmpty(skus)) {
                vo.setMinPrice(skus.stream()
                        .map(ProductSku::getPrice)
                        .filter(Objects::nonNull)
                        .min(BigDecimal::compareTo)
                        .orElse(null));
            }
        }
        return vo;
    }

    @Override
    public List<ProductSku> listSkusByProductIds(List<Long> productIds) {
        if (CollUtil.isEmpty(productIds)) return new ArrayList<>();
        return productSkuMapper.selectList(
                new LambdaQueryWrapper<ProductSku>().in(ProductSku::getProductId, productIds)
        );
    }

    // ==================== 创建 / 更新 / 删除 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProduct(ProductSaveReq req) {
        // 1. 校验分类
        validateCategory(req.getCategoryId());

        // 2. SKU 名称去重
        validateSkuNames(req.getSkuList());

        // 3. 保存 SPU
        Product product = new Product();
        BeanUtil.copyProperties(req, product, "id", "skuList");
        if (product.getSales() == null) product.setSales(0);
        if (product.getViewCount() == null) product.setViewCount(0);
        if (product.getStatus() == null) product.setStatus(ProductStatusEnum.ON_SHELF.getCode());
        productMapper.insert(product);
        log.info("创建商品 id={} name={}", product.getId(), product.getName());

        // 4. 批量保存 SKU
        saveSkus(product.getId(), req.getSkuList());
        return product.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProduct(ProductSaveReq req) {
        if (req.getId() == null) {
            throw new BusinessException(1000, "ID 不能为空");
        }
        Product existing = productMapper.selectById(req.getId());
        if (existing == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        validateCategory(req.getCategoryId());
        validateSkuNames(req.getSkuList());

        // 1. 更新 SPU
        Product product = new Product();
        BeanUtil.copyProperties(req, product, "skuList");
        productMapper.updateById(product);

        // 2. SKU 增量更新：删除本次请求中不存在的旧 SKU，新增的插入，已存在的更新
        List<ProductSku> oldSkus = productSkuMapper.selectList(
                new LambdaQueryWrapper<ProductSku>().eq(ProductSku::getProductId, req.getId())
        );
        Set<Long> reqSkuIds = req.getSkuList().stream()
                .map(ProductSaveReq.ProductSkuReq::getId)
                .filter(Objects::nonNull).collect(Collectors.toSet());

        // 删除：旧 SKU 中不在本次请求的
        List<Long> toDelete = oldSkus.stream()
                .filter(s -> !reqSkuIds.contains(s.getId()))
                .map(ProductSku::getId).toList();
        if (!toDelete.isEmpty()) {
            // 检查是否有未支付订单引用（这里简化为直接删，业务上应加状态校验）
            productSkuMapper.deleteByIds(toDelete);
            log.info("删除 SKU ids={}", toDelete);
        }
        // 新增 / 更新
        saveSkus(req.getId(), req.getSkuList());
        log.info("更新商品 id={}", req.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProduct(Long id) {
        Product existing = productMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        // 1. 删除所有 SKU
        productSkuMapper.delete(
                new LambdaQueryWrapper<ProductSku>().eq(ProductSku::getProductId, id)
        );
        // 2. 删除 SPU
        productMapper.deleteById(id);
        log.info("删除商品 id={}", id);
    }

    // ==================== 状态切换 ====================

    @Override
    public void updateStatus(Long id, Integer status) {
        if (id == null || status == null) {
            throw new BusinessException(1000, "参数错误");
        }
        Product existing = productMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        if (existing.getStatus() != null && existing.getStatus().equals(status)) {
            return; // 状态未变
        }
        Product update = new Product();
        update.setId(id);
        update.setStatus(status);
        productMapper.updateById(update);
        log.info("商品 id={} 状态更新为 {}", id, status);
    }

    @Override
    public void updateHot(Long id, Integer isHot) {
        updateFlag(id, isHot, "isHot");
    }

    @Override
    public void updateNew(Long id, Integer isNew) {
        updateFlag(id, isNew, "isNew");
    }

    private void updateFlag(Long id, Integer value, String field) {
        if (id == null || value == null) {
            throw new BusinessException(1000, "参数错误");
        }
        Product existing = productMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_EXIST);
        }
        Product update = new Product();
        update.setId(id);
        switch (field) {
            case "isHot" -> update.setIsHot(value);
            case "isNew" -> update.setIsNew(value);
        }
        productMapper.updateById(update);
    }

    // ==================== 库存 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void adjustStock(StockAdjustReq req) {
        if (req.getSkuId() == null) {
            throw new BusinessException(1000, "SKU ID 不能为空");
        }
        ProductSku sku = productSkuMapper.selectById(req.getSkuId());
        if (sku == null) {
            throw new BusinessException(1010, "SKU 不存在");
        }

        int newStock;
        if (req.getDelta() != null) {
            newStock = sku.getStock() + req.getDelta();
        } else if (req.getTargetStock() != null) {
            newStock = req.getTargetStock();
        } else {
            throw new BusinessException(1000, "delta 与 targetStock 至少填一个");
        }
        if (newStock < 0) {
            throw new BusinessException(1012, "调整后库存不能小于 0");
        }

        ProductSku update = new ProductSku();
        update.setId(sku.getId());
        update.setStock(newStock);
        productSkuMapper.updateById(update);
        log.info("SKU id={} 库存调整为 {}", req.getSkuId(), newStock);
    }

    @Override
    public boolean decrStock(Long skuId, Integer quantity) {
        if (skuId == null || quantity == null || quantity <= 0) {
            throw new BusinessException(1000, "参数错误");
        }
        int affected = productSkuMapper.decrStock(skuId, quantity);
        return affected > 0;
    }

    @Override
    public void incrStock(Long skuId, Integer quantity) {
        if (skuId == null || quantity == null || quantity <= 0) {
            throw new BusinessException(1000, "参数错误");
        }
        int affected = productSkuMapper.incrStock(skuId, quantity);
        if (affected == 0) {
            log.warn("释放库存失败 skuId={} quantity={}", skuId, quantity);
        }
    }

    // ==================== 浏览量 ====================

    @Override
    public void incrViewCount(Long id) {
        // 简单实现：直接 UPDATE；高并发可改为 Redis INCR + 定时落库
        Product p = productMapper.selectById(id);
        if (p == null) return;
        Product update = new Product();
        update.setId(id);
        update.setViewCount(p.getViewCount() == null ? 1 : p.getViewCount() + 1);
        productMapper.updateById(update);
    }

    // ==================== 私有方法 ====================

    private void saveSkus(Long productId, List<ProductSaveReq.ProductSkuReq> skuReqs) {
        for (ProductSaveReq.ProductSkuReq req : skuReqs) {
            ProductSku sku = new ProductSku();
            BeanUtil.copyProperties(req, sku, "id");
            sku.setProductId(productId);
            if (sku.getStock() == null) sku.setStock(0);
            if (sku.getSales() == null) sku.setSales(0);
            if (sku.getSort() == null) sku.setSort(0);
            if (sku.getId() == null) {
                productSkuMapper.insert(sku);
            } else {
                productSkuMapper.updateById(sku);
            }
        }
    }

    private void validateCategory(Long categoryId) {
        if (categoryId == null) {
            throw new BusinessException(1000, "分类不能为空");
        }
        Category category = categoryMapper.selectById(categoryId);
        if (category == null) {
            throw new BusinessException(ResultCode.CATEGORY_NOT_EXIST);
        }
    }

    private void validateSkuNames(List<ProductSaveReq.ProductSkuReq> skus) {
        if (CollUtil.isEmpty(skus)) {
            throw new BusinessException(1000, "至少需要一个 SKU");
        }
        Set<String> names = new HashSet<>();
        for (ProductSaveReq.ProductSkuReq sku : skus) {
            if (!names.add(sku.getSkuName())) {
                throw new BusinessException(1003, "SKU 名称重复：" + sku.getSkuName());
            }
        }
    }
}
