package nccloud.web.mmpac.pickm.action;

import nc.bs.dao.BaseDAO;
import nc.bs.uapbd.util.MyHelper;
import nc.itf.ic.m4a.IGeneralInMaintain;
import nc.itf.mmpac.pickm.IPickmQueryService;
import nc.itf.uap.pf.busiflow.PfButtonClickContext;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.pubitf.para.SysInitQuery;
import nc.util.mmf.busi.service.PFPubService;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.vo.bd.stordoc.StordocVO;
import nc.vo.fi.pub.SqlUtils;
import nc.vo.ic.m4a.entity.GeneralInBodyVO;
import nc.vo.ic.m4a.entity.GeneralInHeadVO;
import nc.vo.ic.m4a.entity.GeneralInVO;
import nc.vo.mmpac.pickm.entity.AggPickmVO;
import nc.vo.mmpac.pickm.entity.PickmHeadVO;
import nc.vo.mmpac.pickm.entity.PickmItemVO;
import nc.vo.mmpac.pickm.enumeration.FbillstatusEnum;
import nc.vo.mmpac.pickm.enumeration.FsourcetypeEnum;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.compiler.PfParameterVO;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.scmpub.res.billtype.ICBillType;
import nccloud.commons.lang.StringUtils;
import nccloud.dto.mmpac.pickm.pub.entity.PickmQueryInfoDTO;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.core.json.IJson;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.json.JsonFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 备料计划转库存的其它入库
 *
 * @author mzr
 * @date 2025/7/4
 */
public class PickmToGeneralInAction implements ICommonAction {

    public BaseDAO dao;

    public BaseDAO getDao() {
        if (dao == null) {
            dao = new BaseDAO();
        }
        return dao;
    }

    @Override
    public Object doAction(IRequest request) {
        String read = request.read();
        IJson json = JsonFactory.create();
        try {
            // 获取请求查询信息
            PickmQueryInfoDTO paramDTO = json.fromJson(read, PickmQueryInfoDTO.class);
            // 获取主键
            String[] cpickmids = paramDTO.getCpickmids();
            String[] cpickmbids = paramDTO.getCpickmbids();
            if (MMValueCheck.isEmpty(cpickmids) && (null == cpickmbids || cpickmbids.length == 0)) {
                return null;
            }
            AggPickmVO[] aggVOs = null;
            IPickmQueryService service = ServiceLocator.find(IPickmQueryService.class);
            if (MMValueCheck.isNotEmpty(cpickmbids)) {
                aggVOs = service.queryAggPickmVObyBid(cpickmbids);
            } else if (MMValueCheck.isNotEmpty(cpickmids)) {
                aggVOs = service.queryBillsByPks(cpickmids);
            }
            if (MMValueCheck.isEmpty(aggVOs)) {
                /*@res "单据已被修改或删除，请刷新界面重新操作！"*/
                ExceptionUtils.wrapBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("5008100_0", "05008100-0009"));
            }
            // 过滤
            this.filterAggPickmVO(aggVOs);
            // 转换数据
            GeneralInVO[] inVOS = convertToGeneralInVO(aggVOs, null);
            for (GeneralInVO inVO : inVOS) {
                GeneralInBodyVO[] bodys = inVO.getBodys();
                for (GeneralInBodyVO body : bodys) {
                    // cgeneralbid.nnum
                    if (body.getNnum() == null) {
                        body.setNnum(UFDouble.ZERO_DBL);
                    }
                    // NCCForUAPLogger.debug("cgeneralbid.nnum = " + body.getNnum());
                }
            }
            // 其它入库新增
            IGeneralInMaintain generalInMaintain = ServiceLocator.find(IGeneralInMaintain.class);
            GeneralInVO[] insertVos = generalInMaintain.insert(inVOS);
            // NCCForUAPLogger.debug("vbillcode = " + insertVos[0].getHead().getVbillcode());
            Map<String, Object> returnMap = new HashMap<>();
            returnMap.put("data", insertVos);
            returnMap.put("success", true);
            return returnMap;
        } catch (Exception e) {
            ExceptionUtils.wrapException(e);
        }
        return null;
    }

    /**
     * 方法功能描述：批量执行VO转换，若来源及目标单据类型没有注册或传入来源单据不能转换，则抛出业务异常
     *
     * @param sourceBillVOs AggregatedValueObject[]型参数，来源单据VO数组
     * @param srcParaVo     PfParameterVO型参数，平台的运行参数类，一般为NULL即可
     * @return AggregatedValueObject[]型VO转换后的目标单据数组
     * @throws BusinessException 若VO转换失败，则抛出业务异常
     */
    private GeneralInVO[] convertToGeneralInVO(AggregatedValueObject[] sourceBillVOs, PfParameterVO srcParaVo)
            throws BusinessException {
        // 来源交易类型或单据类型，需要在单据类型中注册
        String srcBillOrTranstype = "55A3";
        // 目标交易类型或单据类型，需要在单据类型中注册
        String destBillOrTranstype = ICBillType.GeneralIn.getCode();
        // classifyMode int型参数，调用模式，参照PfButtonClickContext中定义，代码中调用为接口方式 ClassifyByItfdef
        int classifyMode = PfButtonClickContext.ClassifyByItfdef;
        GeneralInVO[] inVOS = (GeneralInVO[]) PFPubService.runChangeData(srcBillOrTranstype, destBillOrTranstype, sourceBillVOs, srcParaVo, classifyMode);
        if (MMValueCheck.isEmpty(inVOS)) {
            ExceptionUtils.wrapBusinessException("备料计划转换其它入库失败");
        }
        String pkOrg = inVOS[0].getParentVO().getPk_org();
        String typeCode = SysInitQuery.getParaString(pkOrg, "ICIN_TYPE");
        String warehouseCode = SysInitQuery.getParaString(pkOrg, "ICIN_CK");
        if (StringUtils.isEmpty(typeCode) || StringUtils.isEmpty(warehouseCode)) {
            ExceptionUtils.wrapBusinessException("当前组织缺失参数配置,请前往 [业务参数设置-组织] 配置仓库或入库类型参数");
        }
        String pk_billtypeid = MyHelper.transferField(BilltypeVO.TABLENAME, BilltypeVO.PK_BILLTYPE_ID, BilltypeVO.PK_BILLTYPECODE, typeCode);
        SqlBuilder sqlBuilder = new SqlBuilder();
        sqlBuilder.append(" select " + StordocVO.PK_STORDOC);
        sqlBuilder.append(" from " + StordocVO.getDefaultTableName());
        sqlBuilder.append(" where dr = 0");
        sqlBuilder.append(" and ");
        sqlBuilder.append(StordocVO.CODE, warehouseCode);
        sqlBuilder.append(" and ");
        sqlBuilder.append(StordocVO.PK_ORG, pkOrg);
        // NCCForUAPLogger.debug("sqlBuilder = " + sqlBuilder);
        String warehouseId = (String) getDao().executeQuery(sqlBuilder.toString(), new ColumnProcessor());
        // NCCForUAPLogger.debug("warehouseId = " + warehouseId);
        for (GeneralInVO inVO : inVOS) {
            // 其它入库单的仓库、交易类型取自【业务参数设置】的默认值
            GeneralInHeadVO head = inVO.getHead();
            // head.setCtrantypeid("0001A110000000001S1E");
            head.setCtrantypeid(pk_billtypeid);
            head.setVtrantypecode(typeCode);
            head.setCwarehouseid(warehouseId);
        }
        return inVOS;
    }

    /*
     * 过滤备料计划 审批通过=1，上游生产订单行是投放状态，已生成的不能再生成
     * fitemstatus 行状态 自由=0,审批通过=4,投放=1,完工=2,关闭=3
     */
    private void filterAggPickmVO(AggPickmVO[] aggVos) throws BusinessException {
        if (aggVos == null) {
            return;
        }
        for (AggPickmVO aggvo : aggVos) {
            PickmHeadVO head = aggvo.getParentVO();
            if (!FbillstatusEnum.AUDIT_STATE.equalsValue(head.getFbillstatus())) {
                ExceptionUtils.wrapBusinessException("请选择审核通过的备料计划");
            }
            // 校验是否已经生成过去其它入库
            PickmItemVO[] items = (PickmItemVO[]) aggvo.getChildren(PickmItemVO.class);
            String[] pickmBidArray = Arrays.stream(items)
                    .map(PickmItemVO::getCpickm_bid)
                    .toArray(String[]::new);
            String bidStr = SqlUtils.getInStr("csourcebillbid", pickmBidArray, true);
            String countSql = "SELECT count(1) FROM ic_generalin_b"
                    + " WHERE dr = 0 and " + bidStr;
            Integer num = (Integer) getDao().executeQuery(countSql, new ColumnProcessor());
            if (num > 0) {
                ExceptionUtils.wrapBusinessException("存在已生成其它入库的行");
            }
            // 如果来源于生产订单，判断上游生产订单行是投放状态
            if (FsourcetypeEnum.MOBILL_STATE.equalsValue(head.getFsourcetype())) {
                SqlBuilder sqlBuilder = new SqlBuilder();
                sqlBuilder.append(" select fitemstatus");
                sqlBuilder.append(" from mm_mo");
                sqlBuilder.append(" where dr = 0");
                sqlBuilder.append(" and ");
                sqlBuilder.append("cmoid", head.getCsourcebillrowid());// 来源生产订单明细id
                Integer fitemstatus = (Integer) getDao().executeQuery(sqlBuilder.toString(), new ColumnProcessor());
                if (fitemstatus != 1) {
                    ExceptionUtils.wrapBusinessException("上游的生产订单行需要为投放状态");
                }
            }

        }
    }
}
