package cn.ysk.cashier.mybatis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapProxy;
import cn.hutool.core.util.StrUtil;
import cn.ysk.cashier.dto.product.PadProductCategoryDTO;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mybatis.mapper.*;
import cn.ysk.cashier.mybatis.service.TbPadProductCategoryService;
import cn.ysk.cashier.pojo.product.*;
import cn.ysk.cashier.repository.product.TbProductSkuResultRepository;
import cn.ysk.cashier.utils.PageUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Pad商品自定义分类
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 2.0 2024-10-22
 */
@Service
public class TbPadProductCategoryServiceImpl extends ServiceImpl<TbPadProductCategoryMapper, TbPadProductCategory> implements TbPadProductCategoryService {

    @Resource
    private TbPadLayoutMapper tbPadLayoutMapper;

    @Resource
    private TbPadProductCategoryDetailMapper tbPadProductCategoryDetailMapper;
    @Resource
    private TbProductMapper tbProductMapper;
    @Resource
    private TbProductSkuResultRepository productSkuResultRepository;
    @Resource
    private TbProducSkutMapper producSkutMapper;

    @Override
    public Map<String, Object> findPage(Map<String, Object> params) {
        MapProxy mapProxy = MapProxy.create(params);
        int pageNum = mapProxy.getInt("page", 1);
        int pageSize = mapProxy.getInt("size", 10);
        Page<PadProductCategoryDTO> page = new Page<>(pageNum, pageSize);
        page.addOrder(OrderItem.asc("sort"));
        params.put("page", page);
        List<PadProductCategoryDTO> list = baseMapper.findList(params);
        return PageUtil.toPlusPage(list, Convert.toInt(page.getTotal()));
    }

    @Override
    public PadProductCategoryDTO get(Long id) {
        TbPadProductCategory entity = baseMapper.selectById(id);
        if (entity == null) {
            throw new BadRequestException("id对应的数据不存在");
        }
        TbPadLayout padLayout = tbPadLayoutMapper.selectById(entity.getPadLayoutId());
        if (padLayout == null) {
            throw new BadRequestException("引用的布局版式不存在");
        }
        Map<String, Object> params = new HashMap<>(2);
        params.put("id", id);
        params.put("shopId", entity.getShopId());
        List<PadProductCategoryDTO> list = baseMapper.findList(params);
        PadProductCategoryDTO dto = list.get(0);
        if (entity.getProductCategoryId().longValue() == 0L) {
            dto.setProductCategoryName("推荐菜");
        }
        List<TbPadProductCategoryDetail> subList = tbPadProductCategoryDetailMapper.selectList(Wrappers.<TbPadProductCategoryDetail>lambdaQuery().eq(TbPadProductCategoryDetail::getPadProductCategoryId, entity.getId()));
        if (CollUtil.isNotEmpty(subList)) {
            List<Long> productIdList = subList.stream().map(TbPadProductCategoryDetail::getProductId).collect(Collectors.toList());
            dto.setProductIdList(productIdList);
            List<List<Long>> splitIdList = CollUtil.split(productIdList, 10);
            List<TbProduct> productList = dto.getProductList();
            for (List<Long> ids : splitIdList) {
                List<TbProduct> splitList = tbProductMapper.selectList(Wrappers.<TbProduct>lambdaQuery().in(TbProduct::getId, ids));
                for (TbProduct item : splitList) {
                    TbProductSkuResult skuResult = productSkuResultRepository.findById(item.getId()).orElse(null);
                    item.setSkuResult(skuResult);
                    List<Map<String, Object>> maps = buildSpecList(skuResult, item);
                    item.setSpecList(maps);
                    productList.add(item);
                }
            }
            dto.setProductList(productList);
        }
        return dto;
    }

    private List<Map<String, Object>> buildSpecList(TbProductSkuResult skuResult, TbProduct item) {
        List<Map<String, Object>> specList = new ArrayList<>();
        List<TbProductSku> tbProductSkus = producSkutMapper.selectList(new LambdaQueryWrapper<TbProductSku>().eq(TbProductSku::getIsDel, 0)
                .eq(TbProductSku::getIsPauseSale, 0)
                .eq(TbProductSku::getProductId, item.getId())
                .eq(TbProductSku::getIsGrounding, 1)
                .select(TbProductSku::getId, TbProductSku::getSpecSnap, TbProductSku::getStockNumber, TbProductSku::getSalePrice, TbProductSku::getSuit));

        String tagSnap = null;
        if (skuResult != null) {
            tagSnap = skuResult.getTagSnap();
        }
        List<String> result = new ArrayList<>();

        if (StrUtil.isNotBlank(tagSnap)) {
            JSONArray tagSnaps = JSONObject.parseArray(tagSnap);
            List<List<String>> valuesList = new ArrayList<>();

            // 提取所有 value 的列表
            for (int i = 0; i < tagSnaps.size(); i++) {
                JSONObject jsonObject = tagSnaps.getJSONObject(i);
                String[] values = jsonObject.getString("value").split(",");
                valuesList.add(Arrays.asList(values));
            }
            // 生成所有可能的排列组合
            generateCombinations(valuesList, 0, new ArrayList<>(), result);

        }

        tbProductSkus.forEach(item2 -> {
            Map<String, Object> itemMap = BeanUtil.beanToMap(item2, false, true);

            itemMap.put("stockNumber", item.getStockNumber());

            specList.add(itemMap);
        });

        ArrayList<HashMap<String, Object>> otherVal = new ArrayList<>();
        for (String res : result) {
            boolean found = false;
            for (Map<String, Object> spec : specList) {
                if (spec.get("specSnap") != null && res.equals(spec.get("specSnap").toString())) {
                    spec.put("isGrounding", true);
                    found = true;
                    break;
                }
            }
            if (!found) {
                HashMap<String, Object> itemMap = new HashMap<>();
                itemMap.put("specSnap", res);
                itemMap.put("skuId", null);
                itemMap.put("isGrounding", false);
                otherVal.add(itemMap);
            }
        }
        specList.addAll(otherVal);
        return specList;
    }

    private static void generateCombinations(List<List<String>> valuesList, int index, List<String> current, List<String> result) {
        if (index == valuesList.size()) {
            result.add(String.join(",", current));
            return;
        }

        for (String value : valuesList.get(index)) {
            current.add(value);
            generateCombinations(valuesList, index + 1, current, result);
            current.remove(current.size() - 1); // 回溯
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(PadProductCategoryDTO dto) {
        Long padLayoutId = dto.getPadLayoutId();
        if (padLayoutId == null) {
            throw new BadRequestException("布局版式id不能为空");
        }
        Long productCategoryId = dto.getProductCategoryId();
        if (productCategoryId == null) {
            throw new BadRequestException("商品分类不能为空");
        }
        Long shopId = dto.getShopId();
        if (shopId == null) {
            throw new BadRequestException("店铺id不能为空");
        }
        Integer sort = dto.getSort();
        if (sort == null) {
            throw new BadRequestException("排序码不能为空");
        }
        if (sort.intValue() < 0) {
            throw new BadRequestException("排序码不能小于0");
        }
        List<Long> productIdList = dto.getProductIdList();
        if (CollUtil.isEmpty(productIdList)) {
            throw new BadRequestException("商品id列表不能为空");
        }
        TbPadLayout padLayout = tbPadLayoutMapper.selectById(padLayoutId);
        if (padLayout == null) {
            throw new BadRequestException("引用的布局版式不存在");
        }
        if (padLayout.getDelFlag() == 1) {
            throw new BadRequestException("引用的布局版式已停用");
        }
        Integer maximum = padLayout.getMaximum();
        if (productIdList.size() > maximum.intValue()) {
            throw new BadRequestException("商品数量不能超过布局版式最大限制：" + maximum.intValue());
        }
        TbPadProductCategory entity = new TbPadProductCategory();
        BeanUtil.copyProperties(dto, entity);
        entity.setCreateTime(new Date());
        super.save(entity);
        for (Long productId : productIdList) {
            TbPadProductCategoryDetail subEntity = new TbPadProductCategoryDetail();
            subEntity.setProductId(productId);
            subEntity.setPadProductCategoryId(entity.getId());
            subEntity.setCreateTime(new Date());
            tbPadProductCategoryDetailMapper.insert(subEntity);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PadProductCategoryDTO dto) {
        Long id = dto.getId();
        if (id == null) {
            throw new BadRequestException("id不能为空");
        }
        Long padLayoutId = dto.getPadLayoutId();
        if (padLayoutId == null) {
            throw new BadRequestException("布局版式id不能为空");
        }
        Long productCategoryId = dto.getProductCategoryId();
        if (productCategoryId == null) {
            throw new BadRequestException("商品分类不能为空");
        }
        Long shopId = dto.getShopId();
        if (shopId == null) {
            throw new BadRequestException("店铺id不能为空");
        }
        Integer sort = dto.getSort();
        if (sort == null) {
            throw new BadRequestException("排序码不能为空");
        }
        if (sort.intValue() < 0) {
            throw new BadRequestException("排序码不能小于0");
        }
        List<Long> productIdList = dto.getProductIdList();
        if (CollUtil.isEmpty(productIdList)) {
            throw new BadRequestException("商品id列表不能为空");
        }
        TbPadLayout padLayout = tbPadLayoutMapper.selectById(padLayoutId);
        if (padLayout == null) {
            throw new BadRequestException("引用的布局版式不存在");
        }
        if (padLayout.getDelFlag() == 1) {
            throw new BadRequestException("引用的布局版式已停用");
        }
        Integer maximum = padLayout.getMaximum();
        if (productIdList.size() > maximum.intValue()) {
            throw new BadRequestException("商品数量不能超过布局版式最大限制：" + maximum.intValue());
        }
        TbPadProductCategory entity = baseMapper.selectById(id);
        if (entity == null) {
            throw new BadRequestException("id对应的数据不存在");
        }
        BeanUtil.copyProperties(dto, entity, "createTime");
        entity.setUpdateTime(new Date());
        super.updateById(entity);
        for (Long productId : productIdList) {
            tbPadProductCategoryDetailMapper.delete(Wrappers.<TbPadProductCategoryDetail>lambdaQuery().eq(TbPadProductCategoryDetail::getPadProductCategoryId, entity.getId()));
            TbPadProductCategoryDetail subEntity = new TbPadProductCategoryDetail();
            subEntity.setProductId(productId);
            subEntity.setPadProductCategoryId(entity.getId());
            subEntity.setCreateTime(new Date());
            tbPadProductCategoryDetailMapper.insert(subEntity);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sort(List<PadProductCategoryDTO> sortList) {
        if (CollUtil.isEmpty(sortList)) {
            throw new BadRequestException("排序列表不能为空");
        }
        for (PadProductCategoryDTO dto : sortList) {
            super.update(null, Wrappers.<TbPadProductCategory>lambdaUpdate().eq(TbPadProductCategory::getId, dto.getId()).set(TbPadProductCategory::getSort, dto.getSort()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        super.removeById(id);
        tbPadProductCategoryDetailMapper.delete(Wrappers.<TbPadProductCategoryDetail>lambdaQuery().eq(TbPadProductCategoryDetail::getPadProductCategoryId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copy(Long id) {
        PadProductCategoryDTO dto = get(id);
        dto.setId(null);
        dto.setCreateTime(null);
        dto.setUpdateTime(null);
        save(dto);
    }

}