package com.fjhx.service.product.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.Condition;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.product.ProductCombination;
import com.fjhx.entity.product.ProductInfo;
import com.fjhx.entity.stock.Stock;
import com.fjhx.mapper.product.ProductInfoMapper;
import com.fjhx.params.product.ProductCombinationEx;
import com.fjhx.params.product.ProductInfoVo;
import com.fjhx.service.product.ProductCombinationService;
import com.fjhx.service.product.ProductInfoService;
import com.fjhx.service.stock.StockService;
import com.fjhx.uitl.code.CodeEnum;
import com.fjhx.utils.Assert;
import com.fjhx.utils.FileClientUtil;
import com.fjhx.utils.wrapperUtil.IWrapper;
import com.fjhx.utils.wrapperUtil.KeywordData;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Dept;
import org.springblade.system.feign.ISysClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-11-29
 */
@Service
public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, ProductInfo> implements ProductInfoService {

    @Resource
    private ISysClient iSysClient;

    @Autowired
    private ProductCombinationService productCombinationService;

    @Autowired
    private StockService stockService;

    @Override
    public Page<Map<String, Object>> getPage(Map<String, Object> condition) {
        IWrapper<ProductInfo> wrapper = IWrapper.getWrapper(condition);
        wrapper
                .keyword(new KeywordData(ProductInfo::getName), new KeywordData(ProductInfo::getCode))
                .eq(ProductInfo::getDefinition)
                .eq(ProductInfo::getDeptId)
                .eq(ProductInfo::getType)
                .eq(ProductInfo::getClassifyId)
                .eq(ProductInfo::getCombination)
                .eq(ProductInfo::getProductSpuId)
                .like(ProductInfo::getName)
                .like(ProductInfo::getCode)
                .ge(ProductInfo::getPurchasePrice, condition.get("purchasePriceMin"))
                .le(ProductInfo::getPurchasePrice, condition.get("purchasePriceMax"))
                .ge(ProductInfo::getSellingPrice, condition.get("sellingPriceMin"))
                .le(ProductInfo::getSellingPrice, condition.get("sellingPriceMax"))
                .ge(ProductInfo::getJdPurchasePrice, condition.get("jdPurchasePriceMin"))
                .le(ProductInfo::getJdPurchasePrice, condition.get("jdPurchasePriceMax"))
                .ne(ProductInfo::getProductSpuId, condition.get("excludeProductSpuId"))
                .eq(ObjectUtil.isNotEmpty(condition.get("lifeCycle")),
                        "(CASE " +
                                "WHEN datediff(now(), computing_time) < new_products_day THEN 1 " +
                                "WHEN datediff(now(), computing_time) < (new_products_day + grow_up_day) THEN 2 " +
                                "ELSE 3 " +
                                "END)",
                        condition.get("lifeCycle"))
                .periodTime(ProductInfo::getClearancePeriod)
                .orderByDesc(ProductInfo::getCode);

        Page<Map<String, Object>> page = baseMapper.getPage(createPage(condition), wrapper);

        List<Map<String, Object>> records = page.getRecords();

        if (records.size() == 0) {
            return page;
        }

        // 赋值部门名称
        List<Long> deptIdList = records.stream().map(item -> Convert.toLong(item.get("deptId"))).collect(Collectors.toList());
        Map<Long, Dept> deptMap = iSysClient.getDeptByIdsToMap(deptIdList);

        //查询产品库存
        Map<Long, Stock> stockMap = new HashMap<>();

        // 查询库存量
        if (Func.isNotEmpty(condition.get("warehouseId"))) {
            // 产品ID集合
            List<Long> ids = page.getRecords().stream().map(item -> Convert.toLong(item.get("id"))).distinct().collect(Collectors.toList());
            List<Stock> stocks = stockService.lambdaQuery().eq(Stock::getWarehouseId, condition.get("warehouseId")).in(Stock::getGoodsId, ids).list();
            if (Func.isNotEmpty(stocks)) {
                stockMap = stocks.stream().collect(Collectors.toMap(Stock::getGoodsId, Function.identity(), (key1, key2) -> key2));
            }
        }

        // 产品部门
        for (Map<String, Object> record : records) {
            Dept dept = deptMap.get(Convert.toLong(record.get("deptId")));
            record.put("deptName", dept == null ? "" : dept.getDeptName());

            if (Func.isNotEmpty(stockMap) && Func.isNotEmpty(stockMap.get(Convert.toLong(record.get("id"))))) {
                Stock stock = stockMap.get(Convert.toLong(record.get("id")));
                record.put("stockQuantity", stock.getQuantity());
            }
        }

        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ProductInfoVo productInfoVo) {

        Long deptId = 0L;
        String deptIdStr = AuthUtil.getDeptId();
        if (ObjectUtil.isNotEmpty(deptIdStr)) {
            deptId = Convert.toLong(deptIdStr.split(",")[0]);
        }

        productInfoVo.setComputingTime(new Date());
        productInfoVo.setDeptId(deptId);

        synchronized (this) {
            if (productInfoVo.getDefinition() != null && productInfoVo.getDefinition().equals(1)) {
                productInfoVo.setCode(CodeEnum.MATERIAL.getCode(productInfoVo.getCode()));
            } else if (ObjectUtil.equals(productInfoVo.getType(), 1)) {
                productInfoVo.setCode(CodeEnum.PRODUCT_FINISHED.getCode(productInfoVo.getCode()));
            } else {
                productInfoVo.setCode(CodeEnum.PRODUCT_PARTIALLY_PREPARED.getCode(productInfoVo.getCode()));
            }

            save(productInfoVo);
        }

        if (StatusConstant.YES.equals(productInfoVo.getCombination())) {
            List<ProductCombination> productCombinationList = productInfoVo.getProductCombinationList();
            Assert.notEmpty(productCombinationList, "组合信息不能为空");

            for (ProductCombination productCombination : productCombinationList) {
                productCombination.setProductId(productInfoVo.getId());
            }

            productCombinationService.saveBatch(productCombinationList);
        }

        FileClientUtil.bindingFile(productInfoVo.getId(), productInfoVo.getFileInfoList());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ProductInfoVo productInfoVo) {

        updateById(productInfoVo);

        if (StatusConstant.YES.equals(productInfoVo.getCombination())) {
            List<ProductCombination> productCombinationList = productInfoVo.getProductCombinationList();
            Assert.notEmpty(productCombinationList, "组合信息不能为空");

            List<Long> productCombinationIdList = new ArrayList<>();

            for (ProductCombination productCombination : productCombinationList) {
                productCombination.setProductId(productInfoVo.getId());

                if (ObjectUtil.isNotEmpty(productCombination.getId())) {
                    productCombinationIdList.add(productCombination.getId());
                }
            }

            productCombinationService.remove(q -> q
                    .eq(ProductCombination::getProductId, productInfoVo.getId())
                    .notIn(ProductCombination::getId, productCombinationIdList));

            productCombinationService.saveOrUpdateBatch(productCombinationList);

        }

        FileClientUtil.againBindingFile(productInfoVo.getId(), productInfoVo.getFileInfoList());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(ProductInfoVo productInfoVo) {

        long count = stockService.count(q -> q.eq(Stock::getGoodsId, productInfoVo.getId()).gt(Stock::getQuantity, BigDecimal.ZERO));
        Assert.eqZero(count, "此产品已有库存，无法删除");

        removeById(productInfoVo.getId());
        FileClientUtil.relieveBindingFile(productInfoVo.getId());
    }

    @Override
    public Page<ProductCombinationEx> getCombinationPage(Condition condition) {
        // 产品id
        Long id = condition.getLong("id");
        Assert.notEmpty(id, "产品id不能为空");

        IWrapper<Object> wrapper = IWrapper.getWrapper(condition);
        wrapper.eq("pc", ProductCombination::getProductId, id);

        return baseMapper.getCombinationPage(createPage(condition), wrapper);
    }

}
