package com.czg.service.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.constant.CacheConstant;
import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException;
import com.czg.product.dto.ProdGroupRelationDTO;
import com.czg.product.dto.ProdSkuDTO;
import com.czg.product.entity.*;
import com.czg.product.param.ShopProductSkuParam;
import com.czg.product.service.ProdConsRelationService;
import com.czg.product.service.UProductService;
import com.czg.product.vo.ShopGroupProductVo;
import com.czg.product.vo.ShopProductInfoVo;
import com.czg.product.vo.ShopProductSkuInfoVo;
import com.czg.product.vo.ShopProductVo;
import com.czg.sa.StpKit;
import com.czg.service.product.mapper.ProdGroupMapper;
import com.czg.service.product.mapper.ProdGroupRelationMapper;
import com.czg.service.product.mapper.ProdSkuMapper;
import com.czg.service.product.mapper.ProductMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 1.0 2025-02-16
 */
@Slf4j
@AllArgsConstructor
@Service
public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements UProductService {

    private final ProductMapper productMapper;
    private final ProdSkuMapper prodSkuMapper;
    private final ProdGroupMapper prodGroupMapper;
    private final ProdGroupRelationMapper prodGroupRelationMapper;
    private final ProdConsRelationService prodConsRelationService;


    @Override
    @Cacheable(value = CacheConstant.USER_CLIENT_HOTS_PRODUCT, key = "#shopId", unless = "#result.isEmpty()")
    public List<ShopProductVo> queryHotsProductList(Long shopId) {
        List<ShopProductVo> list = productMapper.selectHotsProductList(shopId);
        list.forEach(item -> {
            List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
                    .eq(ProdSku::getProductId, item.getId())
                    .eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
                    .eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
            item.setSkuList(skuList);
            item.setConsList(prodConsRelationService.list(query()
                    .eq(ProdConsRelation::getProductId, item.getId())
                    .eq(ProdConsRelation::getShopId, item.getShopId())));
        });
        return list;
    }

    @Override
    @Cacheable(value = CacheConstant.USER_CLIENT_GROUPS_PRODUCT, key = "#shopId", unless = "#result.isEmpty()")
    public List<ShopGroupProductVo> queryGroupProductList(Long shopId) {
        List<ShopGroupProductVo> groupList = prodGroupMapper.selectListByQueryAs(
                query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime)
                        .eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE)
                        .orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class);
        List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, null);
        productAllList.forEach(item -> {
            List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
                    .eq(ProdSku::getProductId, item.getId())
                    .eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
                    .eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
            item.setSkuList(skuList);
            item.setConsList(prodConsRelationService.list(query()
                    .eq(ProdConsRelation::getProductId, item.getId())
                    .eq(ProdConsRelation::getShopId, item.getShopId())));
        });
        Map<Long, ShopProductVo> productKv = productAllList.stream().collect(Collectors.toMap(ShopProductVo::getId, shopProductVo -> shopProductVo));
        List<Long> prodGroupIdList = groupList.stream().map(ShopGroupProductVo::getId).distinct().toList();
        List<ProdGroupRelationDTO> relationList = prodGroupIdList.isEmpty() ? new ArrayList<>() :
                prodGroupRelationMapper.selectListByQueryAs(query().select(ProdGroupRelation::getProdGroupId, ProdGroupRelation::getProductId)
                        .in(ProdGroupRelation::getProdGroupId, prodGroupIdList), ProdGroupRelationDTO.class);
        Map<Long, List<Long>> relationKv = relationList.stream().collect(Collectors.groupingBy(ProdGroupRelationDTO::getProdGroupId,
                Collectors.mapping(ProdGroupRelationDTO::getProductId, Collectors.toList())));
        for (ShopGroupProductVo group : groupList) {
            List<Long> productIdList = relationKv.get(group.getId());
            if (CollUtil.isEmpty(productIdList)) {
                group.setProductList(List.of());
                continue;
            }
            List<ShopProductVo> productList = new ArrayList<>();
            for (Long productId : productIdList) {
                ShopProductVo product = productKv.get(productId);
                if (product != null) {
                    ShopProductVo prod = BeanUtil.copyProperties(product, ShopProductVo.class);
                    prod.setShopId(shopId);
                    productList.add(prod);
                }
            }
            // 1-价格从高到低; 2-价格从低到高; 3-销量由高到低；4-销量由低到高；
            if ("1".equals(group.getSortMode())) {
                productList = productList.stream().sorted(Comparator.comparing(ShopProductVo::getSalePrice).reversed()).toList();
            } else if ("2".equals(group.getSortMode())) {
                productList = productList.stream().sorted(Comparator.comparing(ShopProductVo::getSalePrice)).toList();
            } else if ("3".equals(group.getSortMode())) {
                productList = productList.stream().sorted(Comparator.comparing(ShopProductVo::getSalesVolume).reversed()).toList();
            } else if ("4".equals(group.getSortMode())) {
                productList = productList.stream().sorted(Comparator.comparing(ShopProductVo::getSalesVolume)).toList();
            }
            group.setProductList(productList);
        }
        return groupList.stream().filter(group -> CollUtil.isNotEmpty(group.getProductList())).toList();
    }

    @Override
    public ShopProductInfoVo getProductInfo(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        ShopProductInfoVo data = productMapper.selectOneProductInfo(id, shopId);
        if (data == null) {
            throw new CzgException("商品不可售");
        }

        if (StrUtil.isBlank(data.getRelatedRecommend()) || "[]".equals(data.getRelatedRecommend())) {
            data.setRelatedRecommendJson(new ArrayList<>());
        } else {
            List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, JSONArray.parseArray(data.getRelatedRecommend(), Long.class));
            productAllList.forEach(item -> {
                List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
                        .eq(ProdSku::getProductId, item.getId())
                        .eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
                        .eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
                item.setSkuList(skuList);
            });
            data.setRelatedRecommendJson(productAllList);
        }

        return data;
    }

    @Override
    public ShopProductSkuInfoVo getProductSkuInfo(ShopProductSkuParam param) {
        Long shopId = StpKit.USER.getShopId(0L);
        Product product = productMapper.selectOneById(param.getId());
        if (product == null) {
            throw new CzgException("商品信息不存在");
        }
        String specInfo = StrUtil.blankToDefault(param.getSpecInfo(), null);
        ShopProductSkuInfoVo data = prodSkuMapper.selectOneByQueryAs(
                query().eq(ProdSku::getProductId, param.getId())
                        .eq(ProdSku::getShopId, shopId)
                        .eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO)
                        .eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
                        .eq(ProdSku::getSpecInfo, specInfo)
                , ShopProductSkuInfoVo.class);
        // throw new CzgException("商品SKU不可售或不存在");
        if (data != null) {
            return data;
        }
        return null;
    }


    /**
     * 计算是否在可售时间内
     *
     * @param days      星期几，例如 "Monday,Tuesday"
     * @param startTime 起售时间
     * @param endTime   停售时间
     * @return 是否可售时间 1-是，0-否
     */
    @Override
    public Integer calcIsSaleTime(String days, LocalTime startTime, LocalTime endTime) {
        if (StrUtil.isBlank(days) || ObjUtil.isNull(startTime) || ObjUtil.isNull(endTime)) {
            return SystemConstants.OneZero.ZERO;
        }
        String today = getWeekDayEnName();
        List<String> dayList = StrUtil.split(days, ",");
        LocalTime now = LocalTime.now().withNano(0);
        boolean inDays = CollUtil.contains(dayList, today);
        boolean isSaleTime = false;
        if (startTime.isBefore(endTime)) {
            if (now.isAfter(startTime) && now.isBefore(endTime)) {
                isSaleTime = true;
            }
        } else {
            if (now.isAfter(startTime) || now.isBefore(endTime)) {
                isSaleTime = true;
            }
        }
        if(isSaleTime && inDays){
            return SystemConstants.OneZero.ONE;
        }
        return SystemConstants.OneZero.ZERO;
    }

    /**
     * 计算是否在可售时间内
     *
     * @param useTime   开启时间管控 0:否；1:是
     * @param startTime 起售时间
     * @param endTime   停售时间
     * @return 是否可售时间 1-是，0-否
     */
    @Override
    public Integer calcIsSaleTime(int prodIsSaleTime, Integer useTime, LocalTime startTime, LocalTime endTime) {
        if (NumberUtil.nullToZero(useTime) == 0) {
            return prodIsSaleTime;
        }
        if (ObjUtil.isNull(startTime) || ObjUtil.isNull(endTime)) {
            return SystemConstants.OneZero.ZERO;
        }
        LocalTime now = LocalTime.now().withNano(0);
        if (startTime.isBefore(endTime)) {
            if (now.isAfter(startTime) && now.isBefore(endTime)) {
                return SystemConstants.OneZero.ONE;
            }
        } else {
            if (now.isAfter(startTime) || now.isBefore(endTime)) {
                return SystemConstants.OneZero.ONE;
            }
        }
        return SystemConstants.OneZero.ZERO;
    }

    /**
     * 获取当前日期是星期几的英文名称
     *
     * @return 星期几的英文名称，例如 "Monday" 或 "Friday"
     */
    private String getWeekDayEnName() {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 获取当前日期是星期几，返回一个 DayOfWeek 枚举类型的实例
        DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
        return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH);
    }
}
