package com.fs.hisStore.service.impl;

import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.DateUtils;
import com.fs.hisStore.domain.FsStoreProductScrm;
import com.fs.hisStore.domain.FsStoreProductUserEndCategory;
import com.fs.hisStore.domain.FsStoreUserEndCategoryScrm;
import com.fs.hisStore.dto.FsStoreProductSortItemDTO;
import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
import com.fs.hisStore.mapper.FsStoreProductTagRelationScrmMapper;
import com.fs.hisStore.mapper.FsStoreProductUserEndCategoryMapper;
import com.fs.hisStore.mapper.FsStoreUserEndCategoryScrmMapper;
import com.fs.hisStore.service.IFsStoreUserEndCategoryScrmService;
import com.fs.hisStore.vo.FsStoreProductTagNameVO;
import com.fs.hisStore.vo.FsStoreUserEndCategoryProductVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * 商品用户分端类 Service 实现
 */
@Service
public class FsStoreUserEndCategoryScrmServiceImpl implements IFsStoreUserEndCategoryScrmService {

    @Autowired
    private FsStoreUserEndCategoryScrmMapper mapper;

    @Autowired
    private FsStoreProductUserEndCategoryMapper productUserEndCategoryMapper;

    @Autowired
    private FsStoreProductScrmMapper fsStoreProductScrmMapper;

    @Autowired
    private FsStoreProductTagRelationScrmMapper productTagRelationMapper;

    @Autowired
    private RedisCache redisCache;

    /** Redis key 用于存储固定的好评率随机值 */
    private static final String POSITIVE_RATING_REDIS_KEY = "product:positiveRating:fixed:";
    private static final double MIN_RATING = 95.0;
    private static final double MAX_RATING = 99.9;

    @Override
    public List<FsStoreUserEndCategoryProductVO> listProductsByCategoryId(Long categoryId, String keyword) {
        if (categoryId == null) return new ArrayList<>();
        List<Long> productIds = productUserEndCategoryMapper.selectDistinctProductIdsByCategoryId(categoryId, keyword);
        if (productIds == null || productIds.isEmpty()) return new ArrayList<>();
        long total = (productIds instanceof Page) ? ((Page<?>) productIds).getTotal() : productIds.size();
        int pageNum = (productIds instanceof Page) ? ((Page<?>) productIds).getPageNum() : 1;
        int pageSize = (productIds instanceof Page) ? ((Page<?>) productIds).getPageSize() : 10;
        List<FsStoreProductScrm> products = fsStoreProductScrmMapper.getStoreProductInProductIds(productIds);
        Map<Long, FsStoreProductScrm> productMap = products.stream().collect(Collectors.toMap(FsStoreProductScrm::getProductId, p -> p, (a, b) -> a));
        List<FsStoreProductTagNameVO> tagNames = productTagRelationMapper.selectProductTagNamesByProductIds(productIds);
        // 按商品ID分组，每个商品的标签列表按sort排序
        Map<Long, List<FsStoreProductTagNameVO>> tagVoMap = new LinkedHashMap<>();
        for (FsStoreProductTagNameVO tn : tagNames) {
            tagVoMap.computeIfAbsent(tn.getProductId(), k -> new ArrayList<>()).add(tn);
        }
        // 转换为标签名称列表，已按sort排序（SQL已排序）
               Map<Long, List<String>> tagMap = new LinkedHashMap<>();
        for (Map.Entry<Long, List<FsStoreProductTagNameVO>> entry : tagVoMap.entrySet()) {
            List<String> tagNameList = entry.getValue().stream()
                    .map(FsStoreProductTagNameVO::getTagName)
                    .collect(Collectors.toList());
            tagMap.put(entry.getKey(), tagNameList);
        }
        Map<Long, Long> relSortMap = toRelationSortMap(
                productUserEndCategoryMapper.selectSortByCategoryAndProductIds(categoryId, productIds));
        List<FsStoreUserEndCategoryProductVO> result = new ArrayList<>();
        for (Long pid : productIds) {
            FsStoreProductScrm p = productMap.get(pid);
            if (p == null) continue;
            FsStoreUserEndCategoryProductVO vo = new FsStoreUserEndCategoryProductVO();
            vo.setProductId(p.getProductId());
            vo.setProductName(p.getProductName());
            vo.setImage(p.getImage());
            vo.setPrice(p.getPrice());
            vo.setOtPrice(p.getOtPrice());
            vo.setSales(p.getSales());
            vo.setSort(relSortMap.getOrDefault(pid, 0L));
            vo.setTagList(tagMap.getOrDefault(pid, new ArrayList<>()));
            result.add(vo);
        }
        // 包装为 Page 以携带正确的 total，供 getDataTable 使用
        Page<FsStoreUserEndCategoryProductVO> pageResult = new Page<>(pageNum, pageSize);
        pageResult.setTotal(total);
        pageResult.addAll(result);
        return pageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveProductsSort(Long userEndCategoryId, List<FsStoreProductSortItemDTO> items) {
        if (userEndCategoryId == null || items == null || items.isEmpty()) {
            return 0;
        }
        int n = 0;
        for (FsStoreProductSortItemDTO item : items) {
            if (item == null || item.getProductId() == null) {
                continue;
            }
            long s = item.getSort() == null ? 0L : item.getSort();
            if (s < 0) {
                s = 0;
            }
            if (s > 9999) {
                s = 9999;
            }
            n += productUserEndCategoryMapper.updateRelSortByCategoryAndProduct(userEndCategoryId, item.getProductId(), s);
        }
        return n;
    }

    @Override
    public Map<String, Object> listProductsForApp(Long id, String keyword, Integer pageNum, Integer pageSize, Long storeId, Integer position) {
        Map<String, Object> out = new HashMap<>();
        out.put("list", new ArrayList<FsStoreUserEndCategoryProductVO>());
        out.put("total", 0L);
        if (pageNum == null || pageSize == null || pageSize <= 0) return out;
        PageHelper.startPage(pageNum, pageSize);
        List<Long> productIds;
        if (position == null) {
            position = 1;
        }
        if (position == 1 || position == 2) {
            productIds = productUserEndCategoryMapper.selectDistinctProductIdsByPosition(id,storeId, position, keyword);
        } else if (id != null && id != 0L) {
            productIds = productUserEndCategoryMapper.selectDistinctProductIdsByCategoryId(id, keyword);
        } else {
            productIds = productUserEndCategoryMapper.selectDistinctProductIds(keyword);
        }
        long total = productIds instanceof Page ? ((Page<?>) productIds).getTotal() : (productIds != null ? productIds.size() : 0);
        if (productIds == null || productIds.isEmpty()) {
            out.put("total", total);
            return out;
        }
        List<FsStoreProductScrm> products = fsStoreProductScrmMapper.getStoreProductInProductIdsForApp(productIds);
        Map<Long, FsStoreProductScrm> productMap = products.stream().collect(Collectors.toMap(FsStoreProductScrm::getProductId, p -> p, (a, b) -> a));
        List<FsStoreProductTagNameVO> tagNames = productTagRelationMapper.selectProductTagNamesByProductIds(productIds);
        // 按商品ID分组，每个商品的标签列表按sort排序
        Map<Long, List<FsStoreProductTagNameVO>> tagVoMap = new LinkedHashMap<>();
        for (FsStoreProductTagNameVO tn : tagNames) {
            tagVoMap.computeIfAbsent(tn.getProductId(), k -> new ArrayList<>()).add(tn);
        }
        // 转换为标签名称列表，已按sort排序（SQL已排序）
        Map<Long, List<String>> tagMap = new LinkedHashMap<>();
        for (Map.Entry<Long, List<FsStoreProductTagNameVO>> entry : tagVoMap.entrySet()) {
            List<String> tagNameList = entry.getValue().stream()
                    .map(FsStoreProductTagNameVO::getTagName)
                    .collect(Collectors.toList());
            tagMap.put(entry.getKey(), tagNameList);
        }
        Map<Long, Long> relSortMap = relationSortMapForApp(id, storeId, position, productIds);
        List<FsStoreUserEndCategoryProductVO> result = new ArrayList<>();
        for (Long pid : productIds) {
            FsStoreProductScrm p = productMap.get(pid);
            if (p == null) continue;
            FsStoreUserEndCategoryProductVO vo = new FsStoreUserEndCategoryProductVO();
            vo.setProductId(p.getProductId());
            vo.setProductName(p.getProductName());
            vo.setImage(p.getImage());
            vo.setPrice(p.getPrice());
            vo.setOtPrice(p.getOtPrice());
            vo.setSales(p.getSales());
            vo.setSort(relSortMap.getOrDefault(pid, 0L));
            vo.setTagList(tagMap.getOrDefault(pid, new ArrayList<>()));
            vo.setPositiveRating(getFixedPositiveRating(p.getProductId()));
            result.add(vo);
        }
        out.put("list", result);
        out.put("total", total);
        return out;
    }

    @Override
    public FsStoreUserEndCategoryScrm selectById(Long id) {
        return mapper.selectById(id);
    }

    @Override
    public List<FsStoreUserEndCategoryScrm> selectList(FsStoreUserEndCategoryScrm query) {
        return mapper.selectList(query);
    }

    @Override
    public List<FsStoreUserEndCategoryScrm> selectListPage(FsStoreUserEndCategoryScrm query) {
        return mapper.selectList(query);
    }

    @Override
    public List<FsStoreUserEndCategoryScrm> selectListForProduct(Long storeId) {
        return mapper.selectListForProduct(storeId);
    }

    @Override
    public List<FsStoreUserEndCategoryScrm> selectTop8ByPosition(Long storeId, Integer position) {
        return mapper.selectTop8ByPosition(storeId, position);
    }

    @Override
    public int insert(FsStoreUserEndCategoryScrm entity) {
        entity.setCreateTime(DateUtils.getNowDate());
        entity.setUpdateTime(DateUtils.getNowDate());
        return mapper.insert(entity);
    }

    @Override
    public int update(FsStoreUserEndCategoryScrm entity) {
        entity.setUpdateTime(DateUtils.getNowDate());
        return mapper.update(entity);
    }

    @Override
    public int deleteById(Long id) {
        productUserEndCategoryMapper.deleteByCategoryIds(new Long[]{id});
        return mapper.deleteById(id);
    }

    @Override
    public int deleteByIds(Long[] ids) {
        if (ids == null || ids.length == 0) return 0;
        productUserEndCategoryMapper.deleteByCategoryIds(ids);
        return mapper.deleteByIds(ids);
    }

    private Map<Long, Long> relationSortMapForApp(Long categoryId, Long storeId, Integer position, List<Long> productIds) {
        if (productIds == null || productIds.isEmpty()) {
            return new HashMap<>();
        }
        if (position != null && (position == 1 || position == 2)) {
            if (categoryId != null && categoryId != 0L) {
                return toRelationSortMap(
                        productUserEndCategoryMapper.selectSortByCategoryAndProductIds(categoryId, productIds));
            }
            return toRelationSortMap(
                    productUserEndCategoryMapper.selectAggSortByPositionAndProductIds(storeId, position, productIds));
        }
        if (categoryId != null && categoryId != 0L) {
            return toRelationSortMap(
                    productUserEndCategoryMapper.selectSortByCategoryAndProductIds(categoryId, productIds));
        }
        return toRelationSortMap(productUserEndCategoryMapper.selectAggSortGlobalAndProductIds(productIds));
    }

    private static Map<Long, Long> toRelationSortMap(List<FsStoreProductUserEndCategory> rows) {
        Map<Long, Long> m = new HashMap<>();
        if (rows == null) {
            return m;
        }
        for (FsStoreProductUserEndCategory row : rows) {
            if (row.getProductId() == null) {
                continue;
            }
            m.put(row.getProductId(), row.getSort() != null ? row.getSort() : 0L);
        }
        return m;
    }

    /**
     * 获取固定的好评率随机值
     * 先从 Redis 获取，如果不存在则生成随机值并保存到 Redis（永久保存）
     * @return 固定的好评率值
     */
    private BigDecimal getFixedPositiveRating(Long productId) {
        // 先从 Redis 获取
        BigDecimal cachedRating = redisCache.getCacheObject(POSITIVE_RATING_REDIS_KEY + productId);
        if (cachedRating != null) {
            return cachedRating;
        }
        
        // Redis 不存在，生成随机值
        double rating = ThreadLocalRandom.current().nextDouble(MIN_RATING, MAX_RATING);
        BigDecimal fixedRating = new BigDecimal(rating).setScale(1, RoundingMode.HALF_UP);
        
        // 保存到 Redis（永久保存，不设置过期时间）
        redisCache.setCacheObject(POSITIVE_RATING_REDIS_KEY + productId, fixedRating);
        
        return fixedRating;
    }
}
