package com.hys.app.service.goods.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hys.app.framework.context.user.UserContext;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.security.model.Seller;
import com.hys.app.framework.util.PageConvert;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.mapper.goods.CategorySpecMapper;
import com.hys.app.mapper.goods.SpecValuesMapper;
import com.hys.app.mapper.goods.SpecificationMapper;
import com.hys.app.model.errorcode.GoodsErrorCode;
import com.hys.app.model.goods.dos.CategoryDO;
import com.hys.app.model.goods.dos.CategorySpecDO;
import com.hys.app.model.goods.dos.SpecValuesDO;
import com.hys.app.model.goods.dos.SpecificationDO;
import com.hys.app.model.goods.vo.SelectVO;
import com.hys.app.model.goods.vo.SpecificationVO;
import com.hys.app.service.goods.CategoryManager;
import com.hys.app.service.goods.SpecificationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 规格项业务类
 *
 * @author fk
 * @version v2.0
 * @since v7.0.0
 * 2018-03-20 09:31:27
 */
@Service
public class SpecificationManagerImpl implements SpecificationManager {

    @Autowired
    private CategoryManager categoryManager;
    @Autowired
    private SpecificationMapper specificationMapper;
    @Autowired
    private CategorySpecMapper categorySpecMapper;
    @Autowired
    private SpecValuesMapper specValuesMapper;
    /**
     * 查询规格项列表
     *
     * @param page
     *            页码
     * @param pageSize
     *            每页数量
     * @param keyword
     * 			  关键字
     * @return WebPage
     */
    @Override
    public WebPage list(long page, long pageSize, String keyword) {

        IPage iPage = this.specificationMapper.selectPage(new Page<>(page, pageSize),
                new QueryWrapper<SpecificationDO>()
                        .eq("disabled", 1)
                        .eq("seller_id", 0)
                        //如果查询关键字不为空
                        .like(StringUtil.notEmpty(keyword), "spec_name", keyword)
                        .orderByDesc("spec_id"));

        return PageConvert.convert(iPage);
    }

    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SpecificationDO add(SpecificationDO specification) {


        //如果是管理端添加的规格，则验证管理端的对个名称是否重复
        if (specification.getSellerId() == 0) {
            this.checkSpecName(specification.getSpecName(), null);
        }

        specification.setDisabled(1);
        this.specificationMapper.insert(specification);

        return specification;
    }
    /**
     * 修改规格项
     *
     * @param specification
     *            规格项
     * @param id
     *            规格项主键
     * @return Specification 规格项
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SpecificationDO edit(SpecificationDO specification, Long id) {

        SpecificationDO model = this.getModel(id);
        if (model == null) {
            throw new ServiceException(GoodsErrorCode.E305.code(), "规格不存在");
        }

        //验证规格名称是否重复
        this.checkSpecName(specification.getSpecName(), id);

        specification.setSpecId(id);
        this.specificationMapper.updateById(specification);
        return specification;
    }


    /**
     * 验证规格名称是否重复
     *
     * @param specName
     * @param specId
     */
    private void checkSpecName(String specName, Long specId) {

        QueryWrapper<SpecificationDO> wrapper = new QueryWrapper<SpecificationDO>()
                .eq("disabled", 1)
                .eq("seller_id", 0)
                .eq("spec_name", specName)
                .ne(specId != null, "spec_id", specId);

        Integer count = this.specificationMapper.selectCount(wrapper).intValue();
        if (count > 0) {
            throw new ServiceException(GoodsErrorCode.E305.code(), "规格名称重复");
        }
    }

    /**
     * 删除规格项
     *
     * @param ids
     *            规格项主键
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(Long[] ids) {

        //查看是否已经有分类绑定了该规格
        List<CategorySpecDO> list = this.categorySpecMapper.selectList(new QueryWrapper<CategorySpecDO>()
                .in("spec_id", Arrays.asList(ids)));

        if (list.size() > 0) {

            throw new ServiceException(GoodsErrorCode.E305.code(), "有分类已经绑定要删除的规格，请先解绑分类规格");
        }

        this.specificationMapper.update(new SpecificationDO(), new UpdateWrapper<SpecificationDO>()
                .set("disabled", 0)
                .in("spec_id", Arrays.asList(ids)));
    }
    /**
     * 获取规格项
     *
     * @param id
     *            规格项主键
     * @return Specification 规格项
     */
    @Override
    public SpecificationDO getModel(Long id) {

        return this.specificationMapper.selectById(id);
    }
    /**
     * 查询分类绑定的规格，系统规格
     *
     * @param categoryId 分类id
     * @return
     */
    @Override
    public List<SelectVO> getCatSpecification(Long categoryId) {

        List<SelectVO> selectVOS = specificationMapper.getCatSpecification(categoryId);

        if (!selectVOS.isEmpty()) {
            for (SelectVO selectVO : selectVOS) {
                if (selectVO.getFalgid() != null && categoryId.toString().equals(selectVO.getFalgid())) {
                    selectVO.setSelected(true);
                } else {
                    selectVO.setSelected(false);
                }
            }
        }
        return selectVOS;
    }
    /**
     * 商家自定义规格
     *
     * @param categoryId 分类id
     * @param specName 规格名称
     * @return
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SpecificationDO addSellerSpec(Long categoryId, String specName) {

        CategoryDO category = categoryManager.getModel(categoryId);
        if (category == null) {
            throw new ServiceException(GoodsErrorCode.E305.code(), "分类不存在");
        }

        Map map = new HashMap<>();
        map.put("category_id", categoryId);
        map.put("seller_id", 0);
        map.put("spec_name", specName);
        Integer count = specificationMapper.checkSellerSpecName(map);

        if (count > 0) {
            throw new ServiceException(GoodsErrorCode.E305.code(), "规格名称重复");
        }

        SpecificationDO specification = new SpecificationDO(specName, 1, "", 0L);
        specification = this.add(specification);

        //保存分类规格的关系
        CategorySpecDO categorySpec = new CategorySpecDO(categoryId, specification.getSpecId());
        this.categorySpecMapper.insert(categorySpec);

        return specification;
    }
    /**
     * 商家查询某分类的规格
     *
     * @param categoryId 分类id
     * @return
     */
    @Override
    public List<SpecificationVO> querySellerSpec(Long categoryId) {
        Seller seller = UserContext.getSeller();
        //查询规格
        List<SpecificationVO> specList = specificationMapper.queryCatSpec(categoryId, seller.getSellerId());
        //没有规格
        if (specList == null || specList.size() == 0) {
            return new ArrayList<>();
        }
        initSpec(specList, seller.getSellerId());

        return specList;

    }

    /**
     * 商家查询某分类的规格值是否存在
     *
     * @param sellerId 商家id
     * @param specId 规格id
     * @param specValue 规格值
     * @return
     */
    @Override
    public boolean flagSellerSpec(Long sellerId, Long specId, String specValue) {
        if (sellerId == null || specId == null || specValue == null) {
            return true;
        }
        Integer count = this.specValuesMapper.selectCount(new QueryWrapper<SpecValuesDO>()
                .eq("seller_id", sellerId)
                .eq("spec_id", specId)
                .eq("spec_value", specValue)
                .last("limit 1")).intValue();
        if (count <= 0) {
            return false;
        }
        return true;
    }

    /**
     * 平台查询某分类绑定的规格信息
     *
     * @param categoryId 分类id
     * @return
     */
    @Override
    public List<SpecificationVO> queryAdminSpec(Long categoryId) {
        //查询规格
        List<SpecificationVO> specList = specificationMapper.queryAdminSpec(categoryId);
        //没有规格
        if (specList == null || specList.size() == 0) {
            return new ArrayList<>();
        }
        initSpec(specList, null);

        return specList;
    }

    /**
     * 初始化规格信息
     * @param specList 规格信息集合
     * @param sellerId 商家ID
     */
    private void initSpec(List<SpecificationVO> specList, Long sellerId) {
        //封装规格id的集合
        List<Long> specIdList = new ArrayList<>();

        for (int i = 0; i < specList.size(); i++) {
            specIdList.add(specList.get(i).getSpecId());
        }

        //查询到的是所有规格的规格值
        List<SpecValuesDO> valueList = new ArrayList<>();
        if (sellerId != null) {
            valueList = specValuesMapper.selectList(new QueryWrapper<SpecValuesDO>()
                    .in("spec_id", specIdList)
                    .and(e -> {
                        e.eq("seller_id", 0).or().eq("seller_id", sellerId);
                    }));
        } else {
            valueList = specValuesMapper.selectList(new QueryWrapper<SpecValuesDO>()
                    .in("spec_id", specIdList).eq("seller_id", 0));
        }


        Map<Long, List<SpecValuesDO>> map = new HashMap<>(valueList.size());
        for (SpecValuesDO specValue : valueList) {

            List<SpecValuesDO> list = map.get(specValue.getSpecId());
            if (list == null) {
                list = new ArrayList<>();
            }
            list.add(specValue);
            map.put(specValue.getSpecId(), list);
        }
        //赋值规格值
        for (SpecificationVO vo : specList) {
            vo.setValueList(map.get(vo.getSpecId()));
        }
    }
}
