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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hys.app.converter.erp.GoodsConverter;
import com.hys.app.converter.erp.ProductStockConverter;
import com.hys.app.framework.context.user.AdminUserContext;
import com.hys.app.framework.database.BaseQueryParam;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.database.mybatisplus.base.BaseServiceImpl;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.util.BeanUtils;
import com.hys.app.mapper.goods.GoodsMapper;
import com.hys.app.model.erp.dos.AreaStock;
import com.hys.app.model.erp.dos.GoodsDO;
import com.hys.app.model.erp.dos.ProductDO;
import com.hys.app.model.erp.dos.ProductStockDO;
import com.hys.app.model.erp.dto.*;
import com.hys.app.model.erp.vo.GoodsVO;
import com.hys.app.model.erp.vo.ProductStockVO;
import com.hys.app.model.erp.vo.ProductVO;
import com.hys.app.model.goods.dos.GoodsGalleryDO;
import com.hys.app.service.erp.GoodsManager;
import com.hys.app.service.erp.ProductManager;
import com.hys.app.service.erp.ProductStockManager;
import com.hys.app.service.goods.GoodsGalleryManager;
import com.hys.app.util.ValidateUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 商品业务层实现
 *
 * @author 张崧
 * 2023-12-26 15:56:58
 */
@Service
@AllArgsConstructor
public class GoodsManagerImpl extends BaseServiceImpl<GoodsMapper, GoodsDO> implements GoodsManager {

    private GoodsConverter converter;
    private ProductStockManager productStockManager;
    private ProductManager productManager;
    private GoodsGalleryManager goodsGalleryManager;
    private ProductStockConverter productStockConverter;

    @Override
    public WebPage<GoodsVO> list(GoodsQueryParams queryParams) {
        WebPage<GoodsDO> webPage = baseMapper.selectPage(queryParams);
        // 查询商品标签
        return converter.convert(webPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(GoodsDTO goodsDTO) {
        checkParams(goodsDTO);
        GoodsDO goodsDO = BeanUtil.copyProperties(goodsDTO, GoodsDO.class);
        List<ProductDO> bean = BeanUtils.toBean(goodsDTO.getProductList(), ProductDO.class);
        // 保存相册
        this.goodsGalleryManager.add(goodsDTO.getImageList(), goodsDO.getId());
        GoodsGalleryDO goodsGallery = goodsGalleryManager.getGoodsGallery(goodsDTO.getImageList().get(0).getOriginal());
        goodsDO.setImageSmallList(goodsGallery.getSmall());
        super.save(goodsDO);
        bean.forEach(item ->item.setGoodsId(goodsDO.getId()));
        productManager.saveBatch(bean);
        for (int i = 1; i <= bean.size(); i++) {
            bean.get(i-1).setSort(bean.get(i-1).getId()+100000000*i);
        }
        productManager.updateBatchById(bean);
        //初始化库存
        productStockManager.intStock(bean,goodsDO);
        ;

        // 发送商品消息
//        GoodsChangeMessage message = new GoodsChangeMessage(GoodsChangeMessage.GoodsChangeType.Add, goodsId);
//        this.messageSender.send(new MqMessage(AmqpExchange.ERP_GOODS_CHANGE, AmqpExchange.ERP_GOODS_CHANGE + "_ROUTING", message));
    }




    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(GoodsDTO goodsDTO,Long id) {
        GoodsDO goodsDO = ValidateUtil.getOne(baseMapper, GoodsDO::getId, id, "商品");
        AdminUserContext.compareCompany(goodsDO.getCompanyId());
        checkParams(goodsDTO);
        // 更新商品
        BeanUtil.copyProperties(goodsDTO, goodsDO);
        //先删除sku在新增
        productManager.remove(new LambdaQueryWrapper<ProductDO>().eq(ProductDO::getGoodsId, goodsDTO.getId()));
        List<ProductDO> bean = BeanUtils.toBean(goodsDTO.getProductList(), ProductDO.class);
        // 保存相册
        goodsGalleryManager.edit(goodsDTO.getImageList(), goodsDTO.getId());
        this.goodsGalleryManager.add(goodsDTO.getImageList(), goodsDO.getId());
        GoodsGalleryDO goodsGallery = goodsGalleryManager.getGoodsGallery(goodsDTO.getImageList().get(0).getOriginal());
        goodsDO.setImageSmallList(goodsGallery.getSmall());
        updateById(goodsDO);
        bean.forEach(item -> item.setGoodsId(goodsDO.getId()));
        productManager.saveBatch(bean);
        for (int i = 1; i <= bean.size(); i++) {
            bean.get(i-1).setSort(bean.get(i-1).getId()+100000000*i);
        }
        productManager.updateBatchById(bean);



        // 发送商品消息
//        GoodsChangeMessage message = new GoodsChangeMessage(GoodsChangeMessage.GoodsChangeType.Edit, goodsDTO.getId());
//        this.messageSender.send(new MqMessage(AmqpExchange.ERP_GOODS_CHANGE, AmqpExchange.ERP_GOODS_CHANGE + "_ROUTING", message));
    }


    /**
     * 校验参数   sku不能重复   条形码不能重复   商品名称不能重复
     *
     * @param goodsDTO
     */
    private void checkParams(GoodsDTO goodsDTO) {
        GoodsDO aDo = getOne(new LambdaQueryWrapper<GoodsDO>()
                .eq(GoodsDO::getName, goodsDTO.getName())
                .ne(ObjectUtil.isNotNull(goodsDTO.getId()), GoodsDO::getId, goodsDTO.getId())
                .last("limit 1"));
        if (ObjectUtil.isNotNull(aDo)) {
            throw new ServiceException("商品名称已存在");
        }

        Set<String> collect = goodsDTO.getProductList().stream().map(ProductDTO::getSku).collect(Collectors.toSet());
        if (collect.size() != goodsDTO.getProductList().size()){
            throw new ServiceException("sku不能重复");
        }

        for (ProductDTO productDTO : goodsDTO.getProductList()) {
            ProductDO productDO = productManager.getOne(new LambdaQueryWrapper<ProductDO>()
                    .eq(ProductDO::getSku, productDTO.getSku())
                    .ne(ObjectUtil.isNotNull(productDTO.getId()), ProductDO::getId, productDTO.getId())
                    .last("limit 1"));
            if (ObjectUtil.isNotNull(productDO)) {
                throw new ServiceException("sku已存在");
            }
            //校验sku是否包含中文
            Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]");
            Matcher matcher = pattern.matcher(productDTO.getSku());
            if (matcher.find()){
                throw new ServiceException("sku不能包含中文");
            }
            ProductDO codeOne = productManager.getOne(new LambdaQueryWrapper<ProductDO>()
                    .eq(ProductDO::getBarCode, productDTO.getBarCode())
                    .ne(ObjectUtil.isNotNull(productDTO.getId()), ProductDO::getId, productDTO.getId())
                    .last("limit 1"));
            if (ObjectUtil.isNotNull(codeOne)) {
                throw new ServiceException("条码已存在");
            }
        }
    }

    @Override
    public GoodsVO getInfo(Long id) {
        GoodsDO goodsDO = getById(id);
        List<ProductDO> list = productManager.list(new LambdaQueryWrapper<ProductDO>().eq(ProductDO::getGoodsId, id));
        List<ProductDTO> bean = BeanUtils.toBean(list, ProductDTO.class);
        GoodsVO goodsVO = BeanUtil.copyProperties(goodsDO, GoodsVO.class);
        goodsVO.setProductList(bean);
        return goodsVO;
    }

    @Override
    public GoodsVO getDetail(Long id) {
        // 商品
        GoodsDO goodsDO = getById(id);
        List<ProductDO> list = productManager.list(new LambdaQueryWrapper<ProductDO>().eq(ProductDO::getGoodsId, id));
        List<ProductDTO> bean = BeanUtils.toBean(list, ProductDTO.class);
        GoodsVO goodsVO = BeanUtil.copyProperties(goodsDO, GoodsVO.class);
        goodsVO.setProductList(bean);
        // 商品相册
        List<GoodsGalleryDO> galleryList = goodsGalleryManager.list(goodsDO.getId());
        goodsVO.setImageList(galleryList);
        return goodsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        GoodsDO goodsDO = ValidateUtil.getOne(baseMapper, GoodsDO::getId, id, "商品");
        AdminUserContext.compareCompany(goodsDO.getCompanyId());
        if (goodsDO.getMarketEnable()) {
            throw new ServiceException("请先下架商品");
        }
        removeById(id);
    }

    @Override
    public long countByCategoryId(Long categoryId) {
        return this.baseMapper.selectCount(new LambdaQueryWrapper<GoodsDO>().eq(GoodsDO::getCategoryId, categoryId));
    }

    @Override
    public Boolean updateCheck(Long id) {
        ProductStockDO one = productStockManager.getOne(new LambdaQueryWrapper<ProductStockDO>().eq(ProductStockDO::getGoodsId, id).gt(ProductStockDO::getUsableStock, 0));
        if (ObjectUtil.isNotNull(one)) {
            return true;
        }

        return false;
    }

    @Override
    public Page<ProductStockVO> getSkuByWarehouse(Long wareHouseId, BaseQueryParam queryParam) {
        List<GoodsDO> list = list(new LambdaQueryWrapper<GoodsDO>().eq(GoodsDO::getMarketEnable, true)
                .eq(ObjectUtil.isNotNull(AdminUserContext.getCompanyId()),GoodsDO::getCompanyId,AdminUserContext.getCompanyId()));
        List<Long> collect = list.stream().map(GoodsDO::getId).collect(Collectors.toList());
        Page<ProductStockDO> page = new Page<>(queryParam.getPageNo(), queryParam.getPageSize());
        Page<ProductStockDO> page1 = productStockManager.page(page, new LambdaQueryWrapper<ProductStockDO>()
                .eq(ObjectUtil.isNotNull(wareHouseId), ProductStockDO::getWarehouseId, wareHouseId)
                .eq(ObjectUtil.isNotNull(AdminUserContext.getCompanyId()), ProductStockDO::getCompanyId, AdminUserContext.getCompanyId())
                .in(CollUtil.isNotEmpty(collect),ProductStockDO::getGoodsId, collect));
        Page<ProductStockVO> convert = productStockConverter.convert(page1);
        for (ProductStockVO record : convert.getRecords()) {
            record.setGoodsVO(BeanUtil.copyProperties(getById(record.getGoodsId()),GoodsVO.class));
            record.setProductVO(BeanUtil.copyProperties(productManager.getById(record.getProductId()),ProductVO.class));
        }
        return convert;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSort(GoodsSortDto sortDto) {
        List<GoodsDO> goodsDOS = new ArrayList<>();
        for (SortItem item : sortDto.getData()) {
//            GoodsDO goodsDO = getById(item.getGoodsId());
//            goodsDO.setSort(item.getSort());
//            goodsDOS.add(goodsDO);
        }
        updateBatchById(goodsDOS);
    }

}

