package com.hzs.scm.pub.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.hzs.common.core.constant.ScmFieldConstants;
import com.hzs.common.core.constant.msg.ScmMsgConstants;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.core.web.controller.BaseController;
import com.hzs.common.core.web.page.TableDataInfo;
import com.hzs.common.domain.sale.classify.BdSpecs;
import com.hzs.common.domain.sale.ext.BdProductExt;
import com.hzs.common.domain.sale.product.BdProductSpecs;
import com.hzs.common.domain.sale.product.ext.BdProductBasExt;
import com.hzs.common.domain.system.base.BdCubasdoc;
import com.hzs.common.domain.system.base.BdStorehouse;
import com.hzs.common.domain.system.sys.SysCorp;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.sale.product.IProductServiceApi;
import com.hzs.scm.ic.param.BatchCodeParam;
import com.hzs.scm.ic.service.IIcBatchCodeService;
import com.hzs.scm.product.service.IBdProductBasService;
import com.hzs.scm.pub.param.ItemSpecsParam;
import com.hzs.scm.trans.param.QueryStoreParam;
import com.hzs.scm.trans.param.TransferItemParam;
import com.hzs.scm.trans.param.TransferParam;
import com.hzs.system.base.ICurrencyServiceApi;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 供应链模块公共的控制类，用于存放公共的校验规则
 * @author: sui q
 * @time: 2023/11/29 11:35
 * @classname: ScmController
 * @package_name: com.hzs.scm.pub.controller
 * version 1.0.0
 */
public abstract class ScmController extends BaseController {

    @DubboReference
    private IProductServiceApi productServiceApi;

    @DubboReference
    private ICurrencyServiceApi currencyServiceApi;

    @Autowired
    private IIcBatchCodeService batchCodeService;

    @Autowired
    private IBdProductBasService productBasService;

    protected TableDataInfo packageTableDataInfo(List<?> oldExtList, List<?> newExtList){
        TableDataInfo dataTable = getDataTable(oldExtList);
        dataTable.setRows(newExtList);
        return dataTable;
    }

    /*
     * @description: 验证产品信息
     * @author: sui q
     * @date: 2023/11/29 11:37
     * @param: null null
     **/
    protected String validateProduct(List<?> generalbParamList, Map<String, BdSpecs> specsMap){
        // 验证产品,验证规格分类是否是在规格里面
        List<BdProductSpecs> productSpecsList = getBdProductSpecs(generalbParamList);
        List<BdProductExt> productExtList = productServiceApi.queryProductDtoById(productSpecsList, SecurityUtils.getPkCountry()).getData();
        // 验证产品数量，产品数量不一样，需要重新选择
        if(productExtList == null || productExtList.size() == 0){
            return ScmMsgConstants.PRODUCT_NOT_EXIST;
        }
        // 封装规格名称
        for (BdProductExt productExt : productExtList) {
            for (BdSpecs bdSpecs : productExt.getSpecsList()) {
                String key = productExt.getPkId() + "_" + bdSpecs.getPkId() + "_" + bdSpecs.getPkSpecsType();
                specsMap.put(key, bdSpecs);
            }
        }
        for (Object itemParam : generalbParamList) {
            packageSpecsParam(specsMap, itemParam);
        }
        return null;
    }

    /*
     * @description: 验证产品基本信息
     * @author: sui q
     * @date: 2023/11/29 11:37
     * @param: null null
     **/
    protected String validateProductBas(List<?> generalbParamList){
        Map<String, BdSpecs> specsMap = new HashMap<>();
        // 验证产品,验证规格分类是否是在规格里面
        List<BdProductSpecs> productSpecsList = getBdProductSpecs(generalbParamList);
        List<BdProductBasExt> productBasExtList = productBasService.queryProductExtBySpecsId(productSpecsList, SecurityUtils.getPkCountry());
        // 验证产品数量，产品数量不一样，需要重新选择
        if(productBasExtList == null || productBasExtList.size() == 0){
            return ScmMsgConstants.PRODUCT_NOT_EXIST;
        }
        // 封装规格名称
        for (BdProductBasExt productExt : productBasExtList) {
            for (BdSpecs bdSpecs : productExt.getSpecsList()) {
                String key = productExt.getPkId() + "_" + bdSpecs.getPkId() + "_" + bdSpecs.getPkSpecsType();
                specsMap.put(key, bdSpecs);
            }
        }
        for (Object generalB: generalbParamList) {
            List<ItemSpecsParam> scmItemSpecsList = ReflectUtils.invokeGetter(generalB, ScmFieldConstants.SCM_ITEM_SPECS_LIST);
            Integer pkProductBas = ReflectUtils.invokeGetter(generalB, ScmFieldConstants.PK_PRODUCT_BAS);
            for (ItemSpecsParam itemSpecsParam : scmItemSpecsList) {
                String key = pkProductBas + "_" + itemSpecsParam.getPkSpecs() + "_" + itemSpecsParam.getPkSpecsType();
                if (specsMap.containsKey(key)) {
                    itemSpecsParam.setSpecsName(specsMap.get(key).getSpecsName());
                }
            }
        }
        return null;
    }

    private List<BdProductSpecs> getBdProductSpecs(List<?> generalbParamList) {
        List<BdProductSpecs> productSpecsList = new ArrayList<>();
        for (Object generalB: generalbParamList) {
            List<ItemSpecsParam> itemSpecsParamList= ReflectUtils.invokeGetter(generalB, ScmFieldConstants.SCM_ITEM_SPECS_LIST);
            for (ItemSpecsParam itemSpecsParam : itemSpecsParamList) {
                BdProductSpecs bdProductSpecs = BdProductSpecs.builder()
                        .pkProductBas(ReflectUtils.invokeGetter(generalB, ScmFieldConstants.PK_PRODUCT_BAS))
                        .pkProduct(ReflectUtils.invokeGetter(generalB, ScmFieldConstants.PK_PRODUCT))
                        .pkSpecsType(itemSpecsParam.getPkSpecsType())
                        .pkId(itemSpecsParam.getPkSpecs())
                        .build();
                productSpecsList.add(bdProductSpecs);
            }
        }
        return productSpecsList;
    }

    /*
     * @description: 验证产品批次号
     * @author: sui q
     * @date: 2023/12/6 16:44
     * @param: null null
     **/
    protected String validateProductBatchCode(List<?> itemParamList, Map<String, BdSpecs> specsMap) {
        if(itemParamList.size() == 0){
            return null;
        }
        Set<Long> batchCodeSet = new HashSet<>();
        List<BatchCodeParam> batchCodeParamList = new ArrayList<>();
        for (Object itemParam : itemParamList) {
            Integer pkProduct = packageSpecsParam(specsMap, itemParam);
            Long pkBatchCode = ReflectUtils.invokeGetter(itemParam, ScmFieldConstants.PK_BATCH_CODE);
            if (pkBatchCode != null) {
                BatchCodeParam batchCodeParam = BatchCodeParam.builder()
                        .pkProduct(pkProduct)
                        .pkBatchCode(pkBatchCode)
                        .build();
                batchCodeParamList.add(batchCodeParam);
                batchCodeSet.add(pkBatchCode);
            }
        }
        // 判断是否有批次，有批次需要验证批次
        if (batchCodeParamList.size() > 0) {
            List<Long> batchCodeList = batchCodeService.queryBatchCodeByProduct(batchCodeParamList);
            for (Long batchCode : batchCodeSet) {
                if (!batchCodeList.contains(batchCode)) {
                    return ScmMsgConstants.BATCH_CODE_NOT_EXIST;
                }
            }
        }
        return null;
    }

    private Integer packageSpecsParam(Map<String, BdSpecs> specsMap, Object itemParam) {
        List<ItemSpecsParam> scmItemSpecsList = ReflectUtils.invokeGetter(itemParam, ScmFieldConstants.SCM_ITEM_SPECS_LIST);
        Integer pkProduct = ReflectUtils.invokeGetter(itemParam, ScmFieldConstants.PK_PRODUCT);
        for (ItemSpecsParam itemSpecsParam : scmItemSpecsList) {
            String key = pkProduct + "_" + itemSpecsParam.getPkSpecs() + "_" + itemSpecsParam.getPkSpecsType();
            if(specsMap.containsKey(key)){
                itemSpecsParam.setSpecsName(specsMap.get(key).getSpecsName());
            }
        }
        return pkProduct;
    }

    /*
     * @description: 验证供应商
     * @author: sui q
     * @date: 2023/11/29 11:58
     * @param: null null
     **/
    protected String validateCuBasDoc(Integer pkCuBasDoc, Integer pkCountry){
        if(pkCuBasDoc != null) {
            // 验证供应商
            BdCubasdoc bdCubasdoc = currencyServiceApi.queryBdCubasdocById(pkCuBasDoc, pkCountry).getData();
            if (bdCubasdoc == null || !Objects.equals(bdCubasdoc.getPkId(), pkCuBasDoc)) {
                return ScmMsgConstants.SUPPLIER_NOT_QUERY;
            }
        }
        return null;
    }

    /*
     * @description: 验证客户
     * @author: sui q
     * @date: 2023/11/29 11:58
     * @param: null null
     **/
    protected String validateCustomer(Integer pkCustomer, Integer pkCountry){
        if(pkCustomer != null) {
            // 验证供应商
            BdCubasdoc bdCubasdoc = currencyServiceApi.queryBdCustomerById(pkCustomer, pkCountry).getData();
            if (bdCubasdoc == null || !Objects.equals(bdCubasdoc.getPkId(), pkCustomer)) {
                return ScmMsgConstants.CUSTOMER_NOT_QUERY;
            }
        }
        return null;
    }

    /*
     * @description: 验证库存公司
     * @author: sui q
     * @date: 2023/11/29 11:58
     * @param: null null
     **/
    protected String validateSysCorp(Integer pkCorp, Integer pkCountry){
        if(pkCorp != null) {
            SysCorp sysCorp = currencyServiceApi.querySysCorp(pkCorp, pkCountry).getData();
            if (sysCorp == null || !Objects.equals(sysCorp.getPkId(), pkCorp)) {
                return ScmMsgConstants.CORP_NOT_QUERY;
            }
        }
        return null;
    }

    /*
     * @description: 验证仓库
     * @author: sui q
     * @date: 2023/11/29 11:59
     * @param: null null
     **/
    protected String validateStorehouse(Set<Integer> storehouseIdSet, Integer pkCountry, Integer pkCorp){
        // 验证仓库，根据采购组织验证
        List<BdStorehouse> bdStorehouseList = currencyServiceApi.queryStorehouseByIds(storehouseIdSet, pkCountry, pkCorp).getData();
        if (CollectionUtil.isEmpty(bdStorehouseList) || bdStorehouseList.size() != storehouseIdSet.size()) {
            return ScmMsgConstants.STOREHOUSE_NOT_QUERY;
        }
        return null;
    }

    /*
     * @description: 验证仓库
     * @author: sui q
     * @date: 2023/11/29 11:59
     * @param: null null
     **/
    protected String validateStorehouse(Map<Integer, List<QueryStoreParam>> storehouseIdMap){
        // 验证仓库，根据采购组织验证
        for(Integer pkCountry :storehouseIdMap.keySet()) {
            List<QueryStoreParam> queryStoreParamList =storehouseIdMap.get(pkCountry);
            for (QueryStoreParam queryStoreParam : queryStoreParamList) {
                Integer pkCorp = queryStoreParam.getPkCorp();
                Set<Integer> storehouseIdSet = new HashSet<>();
                storehouseIdSet.add(queryStoreParam.getPkStorehouse());
                List<BdStorehouse> bdStorehouseList = currencyServiceApi.queryStorehouseByIds(storehouseIdSet, pkCountry, pkCorp).getData();
                if (CollectionUtil.isEmpty(bdStorehouseList) || bdStorehouseList.size() != storehouseIdSet.size()) {
                    return ScmMsgConstants.STOREHOUSE_NOT_QUERY;
                }
            }

        }
        return null;
    }


    /*
     * @description: 封装验证产品基本信息的
     * @author: sui q
     * @date: 2023/12/8 15:13
     * @param: null null
     **/
    protected Map<Integer, BdProductBasExt> getBdProductBasExtMap(Set<Integer> idList) {
        List<BdProductBasExt> bdProductBasExtList = productBasService.queryProductBasByIds(idList, SecurityUtils.getPkCountry());
        if (bdProductBasExtList == null || bdProductBasExtList.size() ==0) {
            return null;
        }
        for (BdProductBasExt bdProductBasExt : bdProductBasExtList) {
            if(bdProductBasExt.getPkProduct() == null){
                return null;
            }
        }
        return bdProductBasExtList.stream().collect(Collectors.toMap(BdProductBasExt::getPkId, product -> product));
    }

    /*
     * @description: 验证有关调拨订单、调拨入库的批次号
     * @author: sui q
     * @date: 2023/12/9 10:22
     * @param: null null
     **/
    protected boolean validateBatchCodeByTransParam(TransferParam transferParam, Map<Integer, BdProductBasExt> bdProductBasExtMap) {
        List<BatchCodeParam> batchCodeParamList = new ArrayList<>();
        Set<Long> batchCodeSet = new HashSet<>();
        for (TransferItemParam transferItemParam : transferParam.getTransferItemParamList()) {
            if (transferItemParam.getPkBatchCode() != null) {
                if(bdProductBasExtMap.containsKey(transferItemParam.getPkProductBas())){
                    transferItemParam.setPkProduct(bdProductBasExtMap.get(transferItemParam.getPkProductBas()).getPkProduct());
                }
                BatchCodeParam batchCodeParam = BatchCodeParam.builder()
                        .pkProduct(transferItemParam.getPkProduct())
                        .pkBatchCode(transferItemParam.getPkBatchCode())
                        .build();
                batchCodeParamList.add(batchCodeParam);
                batchCodeSet.add(transferItemParam.getPkBatchCode());
            }
        }
        if (batchCodeParamList.size() > 0) {
            List<Long> batchCodeList = batchCodeService.queryBatchCodeByProduct(batchCodeParamList);
            for (Long batchCode : batchCodeSet) {
                if (!batchCodeList.contains(batchCode)) {
                    return true;
                }
            }
        }
        return false;
    }

    protected void setScmItemsExcel(Object sourceVo, Object targetVo){
        setScmItemsGeneralExcel(sourceVo, targetVo);
        ReflectUtils.invokeSetter(targetVo, "norigprice", ReflectUtils.invokeGetter(sourceVo, "norigprice"));
        ReflectUtils.invokeSetter(targetVo, "ntaxrate", ReflectUtils.invokeGetter(sourceVo, "ntaxrate"));
        ReflectUtils.invokeSetter(targetVo, "norigtaxprice", ReflectUtils.invokeGetter(sourceVo, "norigtaxprice"));
        ReflectUtils.invokeSetter(targetVo, "norigmny", ReflectUtils.invokeGetter(sourceVo, "norigmny"));
        ReflectUtils.invokeSetter(targetVo, "ntax", ReflectUtils.invokeGetter(sourceVo, "ntax"));
        ReflectUtils.invokeSetter(targetVo, "norigtaxmny", ReflectUtils.invokeGetter(sourceVo, "norigtaxmny"));
    }

    protected void setScmItemsGeneralExcel(Object sourceVo, Object targetVo){
        ReflectUtils.invokeSetter(targetVo, "productCode", ReflectUtils.invokeGetter(sourceVo, "productCode"));
        ReflectUtils.invokeSetter(targetVo, "productName", ReflectUtils.invokeGetter(sourceVo, "productName"));
        ReflectUtils.invokeSetter(targetVo, "specsName", ReflectUtils.invokeGetter(sourceVo, "specsName"));
        ReflectUtils.invokeSetter(targetVo, "unitName", ReflectUtils.invokeGetter(sourceVo, "unitName"));
        ReflectUtils.invokeSetter(targetVo, "storehouseName", ReflectUtils.invokeGetter(sourceVo, "storehouseName"));
        ReflectUtils.invokeSetter(targetVo, "batchCode", ReflectUtils.invokeGetter(sourceVo, "batchCode"));
        ReflectUtils.invokeSetter(targetVo, "nnum", ReflectUtils.invokeGetter(sourceVo, "nnum"));
    }
}
