package nccloud.api.impl.ic.m4d;


import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.scmpub.query.SCMBillQuery;
import nc.itf.scmpub.reference.uap.pf.PfServiceScmUtil;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.pubimpl.ic.api.maintain.BillMaintainTool;
import nc.pubitf.ic.m4d.api.IMaterialOutMaintainAPI;
import nc.vo.bd.material.MaterialVO;
import nc.vo.ic.general.define.ICBillFlag;
import nc.vo.ic.general.define.ICBillHeadVO;
import nc.vo.ic.general.util.ICLocationUtil;
import nc.vo.ic.location.ICLocationVO;
import nc.vo.ic.m4d.entity.MaterialOutBodyVO;
import nc.vo.ic.m4d.entity.MaterialOutHeadVO;
import nc.vo.ic.m4d.entity.MaterialOutVO;
import nc.vo.ic.pub.define.ICPubMetaNameConst;
import nc.vo.pub.BusinessException;
import nc.vo.pub.VOStatus;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.scmpub.check.billvalidate.BillVOsCheckRule;
import nc.vo.scmpub.res.billtype.ICBillType;
import nccloud.api.ic.m4d.IAPIMaterialOutMaintain;
import nccloud.api.impl.ic.m4d.check.CheckMaterialOutSaveValidator;
import nccloud.api.impl.ic.m4d.fill.MaterialOutSaveFillValue;
import nccloud.api.impl.ic.m4d.fill.MaterialOutUpdateFillValue;
import nccloud.api.impl.ic.pub.check.CheckProhibitUpdateFields;
import nccloud.openapi.ic.util.ICAPILocationVOUtils;
import nccloud.openapi.scmpub.pub.TransferCodeToPKTool;
import nccloud.openapi.scmpub.pub.TransferMapToVOTool;
import nccloud.pubift.commen.itf.utils.IHttpPostOtherSys;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 *
 * @Description: 库存材料出库单维护实现类
 *
 * @author: 曹军
 * @date:   2019-5-17 上午10:49:30
 * @version NCC1909
 */

public class APIMaterialOutMaintainImpl implements IAPIMaterialOutMaintain{

//    private static final BaseDAO DAO = new BaseDAO();

//    private static final IHttpPostOtherSys HTTP_POST_OTHER_SYS = NCLocator.getInstance().lookup(IHttpPostOtherSys.class);

    @Override
    public MaterialOutVO[] save(List<Map<String, Object>> paramList) throws BusinessException {
        // MapList转聚合VOList
        List<MaterialOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, MaterialOutVO.class);
        MaterialOutVO[] vos =
                aggVOList.toArray(new MaterialOutVO[aggVOList.size()]);
        // 设置货位序列号VO
        ICAPILocationVOUtils.setLocationVO(ICBillType.MaterialOut.getCode(),vos);
        // 1、传入数据基本非空校验
        BillVOsCheckRule checker =
                new BillVOsCheckRule(new CheckMaterialOutSaveValidator());
        checker.check(vos);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        // 翻译货位
        ICAPILocationVOUtils.translate(vos);

//        boolean isSpecialCase = checkSpecialCondition(paramList);
        // 如果判定成功，处理金思维的材料出库，将来源的相关数据补充上
//        if (isSpecialCase) {
//            processPickingPlanSpecialLogic(vos);
//        }
        //其他数据填充
        new MaterialOutSaveFillValue().setDefaultValue(vos);

        IMaterialOutMaintainAPI materialOut = NCLocator.getInstance().lookup(IMaterialOutMaintainAPI.class);
        // 设置每行行号
        setMaterialOutRowNum(vos);
        return materialOut.insertBills(vos);
    }

    private void setMaterialOutRowNum(MaterialOutVO[] vos) {
        for (int i = 0; i < vos.length; i++) {
            MaterialOutVO vo = vos[i];
            MaterialOutBodyVO[] bodys = vo.getBodys();
            if (bodys != null && bodys.length > 0) {
                for (int j = 0; j < bodys.length; j++) {
                    MaterialOutBodyVO body = bodys[j];
                    body.setCrowno(String.valueOf((j +1)*10));
                }
            }
        }
    }

    @Override
    public MaterialOutVO[] update(List<Map<String, Object>> paramList) throws BusinessException {
        // MapList转聚合VOList
        List<MaterialOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, MaterialOutVO.class);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        MaterialOutVO[] vos =
                aggVOList.toArray(new MaterialOutVO[aggVOList.size()]);
        // 设置货位序列号VO
        ICAPILocationVOUtils.setLocationVO(ICBillType.MaterialOut.getCode(),vos);
        MaterialOutHeadVO newVO = vos[0].getHead();
        String cgeneralhid = newVO.getCgeneralhid();
        if(StringUtils.isEmpty(cgeneralhid)){
            throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0391")/*@res "修改材料出库单请指定表头主键cgeneralhid值。"*/);
        }
        SCMBillQuery<MaterialOutVO> queryTool =
                new SCMBillQuery<MaterialOutVO>(MaterialOutVO.class);
        MaterialOutVO[] materialOutVOs = queryTool.queryVOByIDs(new String[]{cgeneralhid});
        Map<String, ICLocationVO[]> deleteLoc =
                new HashMap<String, ICLocationVO[]>();
        // 加载原始单据和货位信息
        MaterialOutVO[] originBills = queryTool.queryVOByIDs(new String[] {
                cgeneralhid
        });
        ICLocationUtil.loadLocationVOs(originBills);
        if(ArrayUtils.isEmpty(materialOutVOs)){
            throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0360")/*@res "没找到要修改的出库单信息，请检查数据的表头主键cgeneralhid。"*/);
        }else{
            List<String> headProFields = CheckProhibitUpdateFields.getHeadProhibitFields("4D");
            List<String> bodyProFields = CheckProhibitUpdateFields.getBodyProhibitFields("4D");
            MaterialOutHeadVO origVO = materialOutVOs[0].getHead();
            if(origVO.getFbillflag() == null ||
                    0 != ((Integer) ICBillFlag.FREE.value())
                            .compareTo((Integer) origVO.getFbillflag())){
                throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0361")/*@res "当前出库单编号："*/ + origVO.getVbillcode() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0362")/*@res "不是自由状态，不能修改"*/);
            }
            origVO.setStatus(VOStatus.UPDATED);
            for(String attr : newVO.getAttributeNames()){
                if(newVO.getAttributeValue(attr) == null) {
                    continue;
                }
                if(headProFields.contains(attr)
                        && !newVO.getAttributeValue(attr).equals(origVO.getAttributeValue(attr))){
                    throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0363")/*@res "表头字段："*/ + attr + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0364")/*@res "不允许修改。"*/ );
                }
                origVO.setAttributeValue(attr, newVO.getAttributeValue(attr));
            }
            for (MaterialOutVO orivo : originBills) {
                MaterialOutBodyVO[] oribodys = orivo.getBodys();
                for (MaterialOutBodyVO oribody : oribodys) {
                    ICLocationVO[] locationVOs = oribody.getLocationVOs();
                    if (null != locationVOs) {
                        deleteLoc.put(oribody.getCgeneralbid(), locationVOs);
                    }
                }
            }
            if(vos[0].getBodys() != null){
                Map<String, MaterialOutBodyVO> pkbs = new HashMap<String, MaterialOutBodyVO>();
                for(MaterialOutBodyVO origBvo : materialOutVOs[0].getBodys()){
                    origBvo.setStatus(VOStatus.UPDATED);
                    pkbs.put(origBvo.getCgeneralbid(), origBvo);
                }
                for(MaterialOutBodyVO newBvo : vos[0].getBodys()){
                    MaterialOutBodyVO roigBvo = pkbs.get(newBvo.getCgeneralbid());
                    if(newBvo.getCgeneralbid() == null || roigBvo == null){
                        throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0365")/*@res "没有匹配到原始出库单表体信息，请检查数据的表体主键cgeneralbid。"*/);
                    }
                    Set<String> bfields = new HashSet<String>();
                    for(String battr : newBvo.getAttributeNames()){
                        if(newBvo.getAttributeValue(battr) == null) {
                            continue;
                        }
                        if(bodyProFields.contains(battr)
                                && !newBvo.getAttributeValue(battr).equals(roigBvo.getAttributeValue(battr))){
                            throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0366")/*@res "表体字段："*/ + battr + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0364")/*@res "不允许修改。"*/ );
                        }
                        roigBvo.setAttributeValue(battr, newBvo.getAttributeValue(battr));
                        bfields.add(battr);
                    }
                    //设置货位序列号孙表,把原来的孙表删除，修改的货位置为新增
                    if(null != newBvo.getLocationVOs()) {
                        List<ICLocationVO> allloc = new ArrayList<ICLocationVO>();
                        if(null != deleteLoc && null != deleteLoc.get(roigBvo.getCgeneralbid())) {
                            for(ICLocationVO delloc : deleteLoc.get(roigBvo.getCgeneralbid())) {
                                delloc.setStatus(VOStatus.DELETED);
                                allloc.add(delloc);
                            }
                        }
                        for(ICLocationVO loc : newBvo.getLocationVOs()) {
                            loc.setStatus(VOStatus.NEW);
                            allloc.add(loc);
                        }
                        roigBvo.setLocationVOs(allloc.toArray(new ICLocationVO[allloc.size()]));
                    }
                    // 翻译货位
                    ICAPILocationVOUtils.translate(materialOutVOs);
                    //其他数据填充
                    new MaterialOutUpdateFillValue().setDefaultValue(materialOutVOs,bfields);
                }
            }
        }
        BillMaintainTool<MaterialOutVO> tool =
                new BillMaintainTool<MaterialOutVO>(MaterialOutVO.class,
                        ICBillType.MaterialOut.getCode());
        tool.doBeforeInsert(materialOutVOs);
        return NCLocator.getInstance()
                .lookup(nc.itf.ic.m4d.IMaterialOutMaintain.class).update(materialOutVOs,originBills);
    }

    @Override
    public MaterialOutVO[] delete(MaterialOutVO[] vos) throws BusinessException {
        if(ArrayUtils.isEmpty(vos)){
            return null;
        }
        for(MaterialOutVO aggvo : vos){
            ICBillHeadVO parentVO = aggvo.getParentVO();
            if(parentVO.getFbillflag() == null ||
                    0 != ((Integer) ICBillFlag.FREE.value())
                            .compareTo((Integer) parentVO.getFbillflag())){
                throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0361")/*@res "当前出库单编号："*/ + parentVO.getVbillcode() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0367")/*@res "不是自由状态，不能删除"*/);
            }
        }
        return (MaterialOutVO[]) PfServiceScmUtil.processBatch("DELETE", "4D", vos, null, null);
    }

    @Override
    public MaterialOutVO[] sign(MaterialOutVO[] vos) throws BusinessException {
        if(ArrayUtils.isEmpty(vos)){
            return null;
        }
        for(MaterialOutVO aggvo : vos){
            ICBillHeadVO parentVO = aggvo.getParentVO();
            if(parentVO.getFbillflag() == null ||
                    0 != ((Integer) ICBillFlag.FREE.value())
                            .compareTo((Integer) parentVO.getFbillflag())){
                throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0361")/*@res "当前出库单编号："*/ + parentVO.getVbillcode() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0330")/*@res "不是自由状态，不能签字"*/);
            }
            if(aggvo.getChildrenVO() != null && aggvo.getChildrenVO().length > 0){
                if(aggvo.getChildrenVO()[0].getAttributeValue(ICPubMetaNameConst.NNUM) == null){
                    throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0361")/*@res "当前出库单编号："*/ + parentVO.getVbillcode() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0392")/*@res "总数量为空，不能签字"*/);
                }
            }

        }
        ICLocationUtil.loadLocationVOs(vos);
        return (MaterialOutVO[]) PfServiceScmUtil.processBatch("SIGN", "4D", vos, null, null);
    }

    @Override
    public MaterialOutVO[] unSign(MaterialOutVO[] vos) throws BusinessException {
        if(ArrayUtils.isEmpty(vos)){
            return null;
        }
        for(MaterialOutVO aggvo : vos){
            ICBillHeadVO parentVO = aggvo.getParentVO();
            if(parentVO.getFbillflag() == null ||
                    0 != ((Integer) ICBillFlag.SIGN.value())
                            .compareTo((Integer) parentVO.getFbillflag())){
                throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0361")/*@res "当前出库单编号："*/ + parentVO.getVbillcode() + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008027_0","04008027-0332")/*@res "不是签字状态，不能取消签字"*/);
            }
        }
        return (MaterialOutVO[]) PfServiceScmUtil.processBatch("CANCELSIGN", "4D", vos, null, null);
    }

    @Override
    public MaterialOutVO[] saveByRef(List<Map<String, Object>> paramList) throws BusinessException{

        // MapList转聚合VOList
        List<MaterialOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, MaterialOutVO.class);
        MaterialOutVO[] vos =
                aggVOList.toArray(new MaterialOutVO[aggVOList.size()]);
        // 1、传入数据基本非空校验
        BillVOsCheckRule checker =
                new BillVOsCheckRule(new CheckMaterialOutSaveValidator());
        checker.check(vos);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        IMaterialOutMaintainAPI materialOut = NCLocator.getInstance().lookup(IMaterialOutMaintainAPI.class);
        return materialOut.insertBills(vos);
    }

    /**
     * 检查是否满足特殊条件：需要同步的组织
     */
//    private boolean checkSpecialCondition(List<Map<String, Object>> materialOutVOS) throws BusinessException {
//
//        List<MaterialOutVO> aggVOList =
//                TransferMapToVOTool.transferMapToAggVO(materialOutVOS, MaterialOutVO.class);
//        MaterialOutVO[] vos =
//                aggVOList.toArray(new MaterialOutVO[aggVOList.size()]);
//
//        if(Objects.isNull(materialOutVOS)){
//            return false;
//        }
//        for (MaterialOutVO materialOutVO : vos) {
//            MaterialOutHeadVO head = materialOutVO.getHead();
//            // 提取组织
//            String pkOrg = head.getPk_org();
//            // 翻译成code
////            String orgCode = transferCodeByPk(StockOrgVO.getDefaultTableName(),  StockOrgVO.CODE, StockOrgVO.PK_ORG, pkOrg);
//            // 使用统一的组织判断方法
////            if(HTTP_POST_OTHER_SYS.checkIfIncludeOrg(pkOrg)){
////                return true;
////            }
//        }
//        return false;
//    }

    /**
     * 处理备料计划特殊逻辑
     */
//    private void processPickingPlanSpecialLogic(MaterialOutVO[] vos) throws BusinessException {
//
//        for (MaterialOutVO vo : vos) {
//            MaterialOutBodyVO[] bodyVOs = vo.getBodys();
//            if (bodyVOs != null) {
//                for (MaterialOutBodyVO bodyVO : bodyVOs) {
//                    // 获取物料编码
//                    String materialCode =  transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, bodyVO.getCmaterialvid());
//                    if (StringUtils.isEmpty(materialCode)||  StringUtils.isEmpty(bodyVO.getCsourcebillbid())) {
//                        continue;
//                    }
//                    // 基于mmpickmview视图查询备料计划相关数据
//                    String sql = buildPickingPlanQuery(materialCode,bodyVO.getCsourcebillbid());
//
//                    try {
//                        List<Map<String, Object>> pickingPlanData = (List<Map<String, Object>>) DAO.executeQuery(sql, new MapListProcessor());
//
//                        // 不唯一或者找不到，这样是有问题，抛出
//                        if(pickingPlanData==null || pickingPlanData.isEmpty()){
//                            throw new BusinessException("根据生产订单明细主键和物料编码去查询bip的中间视图mmpickmview找不到数据，无法进行材料出库的上游主键赋值，请检查数据,报错SQL:"+sql);
//                        }
//
//                        if(pickingPlanData.size()!=1){
//                            throw new BusinessException("根据生产订单明细主键和物料编码去查询bip的中间视图mmpickmview不唯一，无法进行材料出库的上游主键赋值，请检查数据,报错SQL:"+sql);
//                        }
//
//                        if (pickingPlanData != null && !pickingPlanData.isEmpty()) {
//                            // 处理查询到的备料计划数据
//                            processPickingPlanData(bodyVO, pickingPlanData);
//                        }
//
//                    } catch (Exception e) {
//                        throw new BusinessException("查询备料计划数据失败: " + e.getMessage(), e);
//                    }
//                }
//            }
//        }
//    }

    /**
     * 构建备料计划查询SQL（基于mmpickmview视图）
     */
//    private String buildPickingPlanQuery(String materialCode,String cpmohid) {
//        StringBuilder sql = new StringBuilder();
//        sql.append("SELECT ");
//        sql.append("    CODE,");                    // 物料编码
//        sql.append("    PK_BILLTYPECODE,");         // 备料计划交易类型编码
//        sql.append("    CPICKMID,");                // 备料计划主键
//        sql.append("    CMOID,");                   // 流程生产订单行主键
//        sql.append("    CPMOHID,");                 // 流程生产订单主键
//        sql.append("    VROWNO,");                  // 备料计划明细行号
//        sql.append("    CPICKM_BID ");              // 备料计划明细主键
//        sql.append("FROM MMPICKMVIEW ");
//        sql.append("WHERE CODE = '").append(materialCode).append("' AND ")
//                .append("cmoid ='").append(cpmohid).append("'");
//        return sql.toString();
//    }

    /**
     * 处理备料计划数据
     */
//    private void processPickingPlanData(MaterialOutBodyVO bodyVO, List<Map<String, Object>> pickingPlanData) {
//        if (pickingPlanData == null || pickingPlanData.isEmpty()) {
//            return;
//        }
//
//        Map<String, Object> firstRow = pickingPlanData.get(0);
//
//        // 设置备料计划相关字段
//        if (firstRow.get("cpickmid") != null) {
//            bodyVO.setCsourcebillhid(firstRow.get("cpickmid").toString()); // 来源单据ID
//        }
//
//        if (firstRow.get("cpickm_bid") != null) {
//            bodyVO.setCsourcebillbid(firstRow.get("cpickm_bid").toString()); // 来源单据行ID
//        }
//
//        if (firstRow.get("pk_billtypecode") != null) {
//            bodyVO.setCsourcetranstype(firstRow.get("pk_billtypecode").toString()); // 交易类型编码
//        }
//        bodyVO.setCsourcetype("55A3");
//    }

    /**
     * 根据主键查询编码
     */
//    private String transferCodeByPk(String tableName, String selectField, String pkField, String pk) throws BusinessException {
//        if (nc.vo.cmp.util.StringUtils.isEmpty(pk)) {
//            return null;
//        }
//        SqlBuilder sqlBuilder = new SqlBuilder();
//        sqlBuilder.append(" select " + selectField);
//        sqlBuilder.append(" from " + tableName);
//        sqlBuilder.append(" where ");
//        sqlBuilder.append(pkField, pk);
//        Object o = DAO.executeQuery(sqlBuilder.toString(), new ColumnProcessor());
//        if (o == null) {
//            throw new BusinessException("未查询到编码信息，sql【" + sqlBuilder + "】");
//        }
//        return o.toString();
//    }
}
