package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONArray;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.GenerateCode;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.IGoodsService;
import com.ruoyi.system.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 商品Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-04-28
 */
@Service
public class GoodsServiceImpl implements IGoodsService
{
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;
    @Autowired
    private GoodsTagMapper goodsTagMapper;
    @Autowired
    private ShopServiceImpl shopService;
    @Autowired
    private ShopGoodsMapper shopGoodsMapper;
    @Autowired
    private ShopGoodsSkuMapper shopGoodsSkuMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private GoodsCategoryMapper goodsCategoryMapper;

    /**
     * 查询商品
     * 
     * @param id 商品主键
     * @return 商品
     */
    @Override
    public Goods selectGoodsById(String id)
    {
        Goods goods =  goodsMapper.selectGoodsById(id);
        GoodsTag goodsTag = new GoodsTag();
        goodsTag.setGoodsId(goods.getId());
        goods.setGoodsTagList(goodsTagMapper.selectGoodsTagList(goodsTag).stream().map(GoodsTag::getTag).collect(Collectors.toList()));
        return goods;

    }

    /**
     * 查询商品列表
     * 
     * @param goods 商品
     * @return 商品
     */
    @Override
    public List<Goods> selectGoodsList(Goods goods)
    {
        List<Goods> goodsList = goodsMapper.selectGoodsList(goods);

        for (Goods goods1 : goodsList) {
            GoodsCategory goodsCategory = goodsCategoryMapper.selectGoodsCategoryById(goods1.getCategory());
            goods1.setCategoryName(goodsCategory.getName());
            int count = orderMapper.selectSalesVolume(null,goods1.getId());
            goods1.setSalesVolume(count);
        }

        
        return goodsList;
    }

    /**
     * 新增商品
     * 
     * @param goods 商品
     * @return 结果
     */
    @Override
    @Transactional
    public int insertGoods(Goods goods)
    {
        if(goods.getDiscount().compareTo(goods.getPrice())>0){
           throw new ServiceException("折扣价不能大于等于原价");
        }
        goods.setCode(GenerateCode.getCode("G"));
        goods.setCreatedAt(new Date());
        goods.setUpdatedAt(new Date());
        goods.setIsDeleted(0L);
        goods.setState("1");
        goodsMapper.insertGoods(goods);
        insertgoodsExt(goods);
        return 1;
    }

    private void insertgoodsExt(Goods goods) {
        String specString = goods.getSpec();
        long goodsId = goods.getId();
        if(StringUtils.isNotEmpty(specString)){
            List<Spec> specs = JSONArray.parseArray(specString, Spec.class);
            List<RuleNode> ruleNodes = new ArrayList<>();
            List<RuleNode> ruleNodeList = new ArrayList<>();
            for(int i =0;i<specs.size();i++){
                Spec spec = specs.get(i);
                List<SpecRule> specRules = spec.getSpecRules();
                if(specRules!=null &&!specRules.isEmpty()){
                    if(ruleNodes.isEmpty()){
                        for (SpecRule specRule : specRules) {
                            RuleNode<SpecRule> ruleNode = new RuleNode<>();
                            ruleNode.setRuleNode(specRule);
                            ruleNodes.add(ruleNode);
                            ruleNodeList.add(ruleNode);
                        }
                    }else{
                        ruleNodeList.clear();
                        for (RuleNode<SpecRule> ruleNode : ruleNodes) {
                            putRuleNodeChild(ruleNode,specRules,ruleNodeList);
                        }
                    }
                }
            }
            createSku(ruleNodeList,goodsId,goods.getDiscount(),goods.getPrice());
        }
        List<String> goodsTagList = goods.getGoodsTagList();
        if(goodsTagList!=null &&!goodsTagList.isEmpty()){
            for (String tagName : goodsTagList) {
                GoodsTag goodsTag = new GoodsTag();
                goodsTag.setGoodsId(goodsId);
                goodsTag.setState("1");
                goodsTag.setCreatedAt(new Date());
                goodsTag.setTag(tagName);
                goodsTagMapper.insertGoodsTag(goodsTag);
            }
        }
    }

    private void createSku(List<RuleNode> ruleNodeList, long goodsId, BigDecimal discount,BigDecimal price) {
        for (RuleNode<SpecRule> ruleNode : ruleNodeList) {
            List<SpecRule> specRuleList = new ArrayList<>();
            BigDecimal bigDecimal = new BigDecimal(price.toString());
            BigDecimal disCount = new BigDecimal(discount.toString());
            RuleNode<SpecRule> parentRuleNode = ruleNode.getParentRuleNode();
            specRuleList.add(ruleNode.getRuleNode());
            bigDecimal = bigDecimal.add(ruleNode.getRuleNode().getAmount());
            if(parentRuleNode!=null){
                findPartentRuleNode(parentRuleNode,specRuleList,bigDecimal,disCount);
            }
            GoodsSku goodsSku = new GoodsSku();
            goodsSku.setGoodsId(goodsId);
            goodsSku.setCreatedAt(new Date());
            goodsSku.setIsDeleted("0");
            goodsSku.setUpdatedAt(new Date());
            goodsSku.setPrice(bigDecimal);
            goodsSku.setDiscount(discount);
            goodsSku.setRuleList(JSONArray.toJSONString(specRuleList));
            goodsSkuMapper.insertGoodsSku(goodsSku);
        }
    }

    private void findPartentRuleNode(RuleNode<SpecRule> ruleRuleNode, List<SpecRule> specRuleList, BigDecimal bigDecimal, BigDecimal disCount) {
        specRuleList.add(ruleRuleNode.getRuleNode());
        bigDecimal = bigDecimal.add(ruleRuleNode.getRuleNode().getAmount());
        disCount = disCount.add(ruleRuleNode.getRuleNode().getAmount());
        RuleNode<SpecRule> parentRuleNode = ruleRuleNode.getParentRuleNode();
        if(parentRuleNode!=null){
            findPartentRuleNode(parentRuleNode,specRuleList, bigDecimal, disCount);
        }
    }


    private void putRuleNodeChild(RuleNode ruleNode,List<SpecRule> specRules,List<RuleNode> ruleNodeList) {
        List<RuleNode> childNode = ruleNode.getChildNode();
        if(childNode == null ||childNode.isEmpty()){
            List<RuleNode> ruleNodes = new ArrayList<>();
            ruleNode.setChildNode(ruleNodes);
            for (SpecRule specRule : specRules) {
                RuleNode<SpecRule> ruleNode1 = new RuleNode<>();
                ruleNode1.setRuleNode(specRule);
                ruleNode1.setParentRuleNode(ruleNode);
                ruleNodes.add(ruleNode1);
                ruleNodeList.add(ruleNode1);
            }
        }else{
            for (RuleNode node : childNode) {
                putRuleNodeChild(node,specRules,ruleNodeList);
            }
        }

    }

    /**
     * 修改商品
     * 
     * @param goods 商品
     * @return 结果
     */
    @Override
    public int updateGoods(Goods goods)
    {
        int i =  goodsMapper.updateGoods(goods);
        goodsSkuMapper.deleteGoodsSkuByGoodsId(String.valueOf(goods.getId()));
        goodsTagMapper.deleteGoodsTagByGoodsId(String.valueOf(goods.getId()));
        insertgoodsExt(goods);
        return i;
    }

    /**
     * 批量删除商品
     * 
     * @param ids 需要删除的商品主键
     * @return 结果
     */
    @Override
    public int deleteGoodsByIds(String[] ids)
    {
        return goodsMapper.deleteGoodsByIds(ids);
    }

    /**
     * 删除商品信息
     * 
     * @param id 商品主键
     * @return 结果
     */
    @Override
    public int deleteGoodsById(String id)
    {

        return 1;

    }

    @Override
    public String putShop(Long goodsId, boolean boo) {
        Goods goods = new Goods();
        goods.setId(goodsId);
        goods.setState("3");
        goods.setUpdatedAt(new Date());
        goods.setShelfAt(new Date());
        int i = goodsMapper.updateGoods(goods);
        if(boo&&i>0){
            Shop shop = new Shop();
            shop.setIsDefault(0L);
            List<Shop> shops = shopService.selectShopList(shop);
            for (Shop shop1 : shops) {
                if("3".equals(shop1.getState())){
                    try{
                        shopService.addGoods(shop1.getId(),goodsId);
                    }catch (ServiceException serviceException){

                    }

                }
            }
        }
        return null;
    }

    @Override
    public String offShop(Long goodsId, boolean boo) {
        ShopGoods shopGoods = new ShopGoods();
        shopGoods.setGoodsId(goodsId);
        List<ShopGoods> shopGoodsList = shopGoodsMapper.selectShopGoodsList(shopGoods);
        if(!boo){
            Boolean isExist = shopGoodsList.size()>0;
            if(isExist){
                return "99";
            }
        }
        Goods goods = new Goods();
        goods.setId(goodsId);
        goods.setUpdatedAt(new Date());
        goods.setState("4");
        int i = goodsMapper.updateGoods(goods);
        for (ShopGoods shopGoods1 : shopGoodsList) {
            shopGoodsMapper.deleteShopGoodsById(shopGoods1.getId());
            shopGoodsSkuMapper.deleteShopGoodsSkuByGoodsId(shopGoods1.getGoodsId());
        }

        return i+"";
    }

    @Override
    public String deleteGoodsById(Long id, boolean boo) {
        ShopGoods shopGoods = new ShopGoods();
        shopGoods.setGoodsId(id);
        List<ShopGoods> shopGoodsList = shopGoodsMapper.selectShopGoodsList(shopGoods);
        if(!boo){
            Boolean isExist = shopGoodsList.size()>0;
            if(isExist){
                return "99";
            }
        }
        Goods goods = new Goods();
        goods.setIsDeleted(1L);
        goods.setId(id);
        goods.setState("5");
        goodsMapper.updateGoods(goods);
        goodsSkuMapper.deleteGoodsSkuByGoodsId(String.valueOf(id));
        goodsTagMapper.deleteGoodsTagByGoodsId(String.valueOf(id));
        return "1";
    }

    public List<GoodsSku> getGoodsSkus(long goodsId){
        GoodsSku goodsSku = new GoodsSku();
        goodsSku.setGoodsId(goodsId);
        goodsSku.setIsDeleted("0");
        return goodsSkuMapper.selectGoodsSkuList(goodsSku);

    }

    public String test() {
        Goods goods = goodsMapper.selectGoodsById("21");
        insertgoodsExt(goods);
        return null;

    }


    class RuleNode<T>{

        private RuleNode parentRuleNode;
        private T ruleNode;

        public RuleNode getParentRuleNode() {
            return parentRuleNode;
        }

        public void setParentRuleNode(RuleNode parentRuleNode) {
            this.parentRuleNode = parentRuleNode;
        }

        private List<RuleNode> childNode;


        public T getRuleNode() {
            return ruleNode;
        }

        public void setRuleNode(T ruleNode) {
            this.ruleNode = ruleNode;
        }

        public List<RuleNode> getChildNode() {
            return childNode;
        }

        public void setChildNode(List<RuleNode> childNode) {
            this.childNode = childNode;
        }

    }
}
