package nccloud.api.impl.ic.m4c;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.bs.scmpub.query.SCMBillQuery;
import nc.itf.scmpub.reference.uap.pf.PfServiceScmUtil;
import nc.pubitf.ic.m4c.api.ISaleOutMaintainAPI;
import nc.vo.ic.general.define.ICBillFlag;
import nc.vo.ic.general.define.ICBillHeadVO;
import nc.vo.ic.general.define.MetaNameConst;
import nc.vo.ic.general.util.ICLocationUtil;
import nc.vo.ic.location.ICLocationVO;
import nc.vo.ic.m4c.entity.SaleOutBodyVO;
import nc.vo.ic.m4c.entity.SaleOutHeadVO;
import nc.vo.ic.m4c.entity.SaleOutVO;
import nc.vo.ic.pub.define.ICPubMetaNameConst;
import nc.vo.pub.BusinessException;
import nc.vo.pub.VOStatus;
import nc.vo.pubapp.util.VORowNoUtils;
import nc.vo.scmpub.check.billvalidate.BillVOsCheckRule;
import nc.vo.scmpub.res.billtype.ICBillType;
import nccloud.api.ic.m4c.IAPISaleOutMaintain;
import nccloud.api.impl.ic.m4c.check.CheckSaleOutSaveValidator;
import nccloud.api.impl.ic.m4c.fill.SaleOutSaveFillValue;
import nccloud.api.impl.ic.m4c.fill.SaleOutSaveFromRefFillValue;
import nccloud.api.impl.ic.m4c.fill.SaleOutUpdateFillValue;
import nccloud.api.impl.ic.pub.check.CheckProhibitUpdateFields;
import nccloud.api.impl.ic.pub.rule.ChooseHeadOrg;
import nccloud.commons.lang.ArrayUtils;
import nccloud.commons.lang.StringUtils;
import nccloud.openapi.ic.util.ICAPILocationVOUtils;
import nccloud.openapi.scmpub.pub.TransferCodeToPKTool;
import nccloud.openapi.scmpub.pub.TransferMapToVOTool;

/**
 * @version NCC1909
 * @Description: 销售出库单维护接口实现类
 * @author: 曹军
 * @date: 2019-5-17 上午10:19:25
 */

public class APISaleOutMaintainImpl implements IAPISaleOutMaintain {

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

        return (SaleOutVO[]) PfServiceScmUtil.processBatch("WRITE", "4C", vos, null,
                null);
    }

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

        // MapList转聚合VOList
        List<SaleOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, SaleOutVO.class);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        SaleOutVO[] vos =
                aggVOList.toArray(new SaleOutVO[aggVOList.size()]);
        // 设置货位序列号VO
        ICAPILocationVOUtils.setLocationVO(ICBillType.MaterialOut.getCode(), vos);
        SaleOutHeadVO newVO = vos[0].getHead();
        String cgeneralhid = newVO.getCgeneralhid();
        if (StringUtils.isEmpty(cgeneralhid)) {
            throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
                    .getStrByID("4008027_0", "04008027-0390")/*
             * @res
             * "修改销售出库单请指定表头主键cgeneralhid值。"
             */);
        }
        SCMBillQuery<SaleOutVO> queryTool =
                new SCMBillQuery<SaleOutVO>(SaleOutVO.class);
        SaleOutVO[] saleOutVOs = queryTool.queryVOByIDs(new String[]{
                cgeneralhid
        });
        Map<String, ICLocationVO[]> deleteLoc =
                new HashMap<String, ICLocationVO[]>();
        // 加载原始单据和货位信息
        SaleOutVO[] originBills = queryTool.queryVOByIDs(new String[]{
                cgeneralhid
        });
        ICLocationUtil.loadLocationVOs(originBills);
        if (ArrayUtils.isEmpty(saleOutVOs)) {
            throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
                    .getStrByID("4008027_0", "04008027-0360")/*
             * @res
             * "没找到要修改的出库单信息，请检查数据的表头主键cgeneralhid。"
             */);
        } else {
            List<String> headProFields =
                    CheckProhibitUpdateFields.getHeadProhibitFields("4C");
            List<String> bodyProFields =
                    CheckProhibitUpdateFields.getBodyProhibitFields("4C");
            SaleOutHeadVO origVO = saleOutVOs[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 (SaleOutVO orivo : originBills) {
                SaleOutBodyVO[] oribodys = orivo.getBodys();
                for (SaleOutBodyVO oribody : oribodys) {
                    ICLocationVO[] locationVOs = oribody.getLocationVOs();
                    if (null != locationVOs) {
                        deleteLoc.put(oribody.getCgeneralbid(), locationVOs);
                    }
                }
            }
            if (vos[0].getBodys() != null) {
                Map<String, SaleOutBodyVO> pkbs =
                        new HashMap<String, SaleOutBodyVO>();
                for (SaleOutBodyVO origBvo : saleOutVOs[0].getBodys()) {
                    origBvo.setStatus(VOStatus.UPDATED);
                    pkbs.put(origBvo.getCgeneralbid(), origBvo);
                }
                for (SaleOutBodyVO newBvo : vos[0].getBodys()) {
                    SaleOutBodyVO 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(saleOutVOs);
                    // 其他数据填充
                    new SaleOutUpdateFillValue().setDefaultValue(saleOutVOs, bfields);
                }
            }
        }
        return NCLocator.getInstance()
                .lookup(nc.itf.ic.m4c.self.ISaleOutMaintain.class)
                .update(saleOutVOs, originBills);
    }

    @Override
    public SaleOutVO[] updateAndSign(List<Map<String, Object>> paramList) throws BusinessException {
        SaleOutVO[] updateVOs =NCLocator.getInstance().lookup(IAPISaleOutMaintain.class).update(paramList);
        SaleOutVO[] signVOs =NCLocator.getInstance().lookup(IAPISaleOutMaintain.class).sign(updateVOs);
        return signVOs;
    }

    @Override
    public SaleOutVO[] delete(SaleOutVO[] vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        for (SaleOutVO 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 (SaleOutVO[]) PfServiceScmUtil.processBatch("DELETE", "4C", vos,
                null, null);
    }

    @Override
    public SaleOutVO[] sign(SaleOutVO[] vos) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        for (SaleOutVO 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-0331")/* @res "主数量为空，不能签字" */);
                }
            }

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

    @Override
    public SaleOutVO[] unSign(SaleOutVO[] vos) throws BusinessException {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public SaleOutVO[] saveRefSaleOrder(List<Map<String, Object>> paramList) throws BusinessException {
        // MapList转聚合VOList
        List<SaleOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, SaleOutVO.class);
        SaleOutVO[] vos = aggVOList.toArray(new SaleOutVO[aggVOList.size()]);
        // 1、传入数据基本非空校验
        BillVOsCheckRule checker =
                new BillVOsCheckRule(new CheckSaleOutSaveValidator());
        checker.check(vos);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        // 其他数据填充
        new SaleOutSaveFromRefFillValue().setRefValue(vos, "30");

        // 保存销售出库单
        return (SaleOutVO[]) PfServiceScmUtil.processBatch("WRITE", "4C", vos, null,
                null);

    }

    @Override
    public SaleOutVO[] saveRefDelivery(List<Map<String, Object>> paramList) throws BusinessException {
        // MapList转聚合VOList
        List<SaleOutVO> aggVOList =
                TransferMapToVOTool.transferMapToAggVO(paramList, SaleOutVO.class);
        SaleOutVO[] vos = aggVOList.toArray(new SaleOutVO[aggVOList.size()]);
        // 1、传入数据基本非空校验
        BillVOsCheckRule checker =
                new BillVOsCheckRule(new CheckSaleOutSaveValidator());
        checker.check(vos);
        // 2、编码翻译成pk
        aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);

        // 其他数据填充
        new SaleOutSaveFromRefFillValue().setRefValue(vos, "4331");
        // 保存销售出库单
        return (SaleOutVO[]) PfServiceScmUtil.processBatch("WRITE", "4C", vos, null,
                null);
    }

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

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

        //设置组织vid
        new ChooseHeadOrg().process(vos);
        //设置行号
        VORowNoUtils.setVOsRowNoByRule(vos, MetaNameConst.CROWNO);
        ISaleOutMaintainAPI saleOut = NCLocator.getInstance().lookup(ISaleOutMaintainAPI.class);
        return saleOut.insertBills(vos);
    }
}
