package nc.bs.ic.m4r.approve.rule;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Log;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.vo.bd.cust.CustomerVO;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.rack.RackVO;
import nc.vo.bd.stordoc.StordocVO;
import nc.vo.bd.supplier.SupplierVO;
import nc.vo.ic.m4r.entity.InvCountBillVO;
import nc.vo.ic.m4r.entity.InvCountBodyVO;
import nc.vo.ic.m4r.entity.InvCountHeaderVO;
import nc.vo.org.StockOrgVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.vorg.DeptVersionVO;
import nccloud.pubift.commen.itf.utils.IHttpPostOtherSys;

import java.util.ArrayList;
import java.util.List;


/**
 * 盘点（审批后传MES）
 */
public class AfterApprovingSynchronizeRuleMES implements IRule<InvCountBillVO> {
    private static final String INV_COUNT_URL = "/GTHINKING/AjaxService/N_KCSJJS/101527005.ashx/KCPD_INSERT"; // 盘点单同步接口
    private static final String logginfo = "OALOG";
    private static final Log obmlog = Log.getInstance(logginfo);
    private static final BaseDAO dao = new BaseDAO();
    IHttpPostOtherSys httpPostOtherSys = NCLocator.getInstance().lookup(IHttpPostOtherSys.class);

    public AfterApprovingSynchronizeRuleMES() {
    }

    @Override
    public void process(InvCountBillVO[] invCountBillVOs) {
        try {
            if (invCountBillVOs == null || invCountBillVOs.length == 0) {
                obmlog.debug("AfterApprovingSynchronizeRule-没有要处理的盘点");
                return;
            }
            // 筛选需要处理的单据
            List<InvCountBillVO> filteredBillVOS = checkAndFilterBills(invCountBillVOs);
            if (filteredBillVOS.isEmpty()) {
                obmlog.debug("AfterApprovingSynchronizeRule-没有要处理的组织为电缆的需要同步的盘点");
                return;
            }
            // 处理每个盘点单
            for (InvCountBillVO invCountBillVO : filteredBillVOS) {
                InvCountHeaderVO hvo = invCountBillVO.getParentVO();
                InvCountBodyVO[] bvos = invCountBillVO.getChildrenVO();
                // 构建要发送的数据
                JSONObject syncData = buildSyncData(hvo, bvos);
                // 发送数据到金思维系统（使用HttpPostOtherSysImpl处理网络请求）
                httpPostOtherSys.sendToExternalSystem(INV_COUNT_URL, syncData);
            }
        } catch (Exception e) {
            obmlog.error("AfterApprovingSynchronizeRule-处理异常:" + e.getMessage(), e);
            ExceptionUtils.wrappException(e);
        }
    }

    /**
     * 检查并筛选需要同步的单据
     */
    private List<InvCountBillVO> checkAndFilterBills(InvCountBillVO[] invCountBillVOS) {
        List<InvCountBillVO> result = new ArrayList<>();
        for (InvCountBillVO vo : invCountBillVOS) {
            try {
                String code = transferCodeByPk(StockOrgVO.getDefaultTableName(), StockOrgVO.CODE, StockOrgVO.PK_STOCKORG, vo.getParentVO().getPk_org());
                if (httpPostOtherSys.checkIfIncludeOrg(code)) {
                    result.add(vo);
                }
            } catch (BusinessException e) {
                ExceptionUtils.wrappBusinessException("查询组织时发生错误");
            }
        }
        return result;
    }

    /**
     * 构建符合金思维系统接口规范的请求数据
     * 按照接口文档要求构建JSON结构
     */
    private JSONObject buildSyncData(InvCountHeaderVO hvo, InvCountBodyVO[] bvos) throws BusinessException {
        obmlog.debug("AfterApprovingSynchronizeRule-开始处理盘点单: " + hvo.getVbillcode());
        // 按照新规范构建请求数据
        JSONObject requestBody = new JSONObject();
        JSONObject requestData = new JSONObject();
        // 盘点主信息 盘点单号 为空时自动生成
        requestData.put("PDDH", null);
        // 获取仓库编码
        String warehouseCode = transferCodeByPk(StordocVO.getDefaultTableName(), StordocVO.CODE, StordocVO.PK_STORDOC, hvo.getCwarehouseid());
        requestData.put("CKID", warehouseCode);
        // 盘点部门编码
        String deptCode = transferCodeByPk(DeptVersionVO.getDefaultTableName(), DeptVersionVO.CODE, DeptVersionVO.PK_VID, hvo.getCdptvid());
        requestData.put("BMID", deptCode);
        // 盘点人
        requestData.put("PDR", getStringValue(hvo.getCountoperator()));
        // 日期处理 - 盘点日期
        UFDate dcountdate = hvo.getDcountdate();
        if (dcountdate != null) {
            requestData.put("PDRQ", dcountdate.toString()); // 盘点日期 - 必填
        } else {
            requestData.put("PDRQ", null);
        }
        // 备注
        requestData.put("BZ", getStringValue(hvo.getVnote()));
        // 构建明细数组
        JSONArray details = new JSONArray();
        if (bvos != null) {
            for (InvCountBodyVO bvo : bvos) {
                JSONObject detail = new JSONObject();
                // 获取序号并转换为浮点数
                String crownStr = bvo.getCrowno();
                try {
                    // 序号
                    detail.put("XH", Double.parseDouble(crownStr));
                } catch (NumberFormatException e) {
                    detail.put("XH", null);
                }
                // 物料编码
                detail.put("WLID", transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, bvo.getCmaterialvid()));
                // 货位
                detail.put("KW", transferCodeByPk(RackVO.getDefaultTableName(), RackVO.CODE, RackVO.PK_RACK, bvo.getClocationid()));
                // 物料批号
                detail.put("WLPH", getStringValue(bvo.getVbatchcode()));
                // 盘存数量 -> 实盘主数量
                UFDouble pcNum = bvo.getNcountnum();
                // 账面主数量
                UFDouble zmNum = bvo.getNonhandnum();
                // 如果盘存数量为null赋值为0
                if (pcNum == null) {
                    detail.put("PCSL", 0);
                    pcNum = new UFDouble(0);
                }
                // 如果账面数量为null赋值为0
                if (zmNum == null) {
                    zmNum = new UFDouble(0);
                }
                // 如果二者相等 两个 想减为0  都传0
                if (pcNum.getDouble() == zmNum.getDouble()) {
                    detail.put("PCSL", pcNum.getDouble());
                    detail.put("PYSL", 0);
                    detail.put("PKSL", 0);
                }
                // 盘盈盘亏都是正数
                // 账面数据比实盘数据大时，为盘亏，此时盘盈没有值，盘亏为账面减去实盘；
                // 账面数据比实盘数据小时，为盘盈，此时盘亏没有值，盘盈为实盘减去账面
                if (zmNum.getDouble() > pcNum.getDouble()) {
                    detail.put("PCSL", pcNum.getDouble());
                    detail.put("PYSL", 0);
                    detail.put("PKSL", Math.abs(zmNum.getDouble() - pcNum.getDouble()));
                }
                if (zmNum.getDouble() < pcNum.getDouble()) {
                    detail.put("PCSL", pcNum.getDouble());
                    detail.put("PYSL", Math.abs(pcNum.getDouble() - zmNum.getDouble()));
                    detail.put("PKSL", 0);
                }
                // 盈亏单价
                detail.put("YCDJ", null);
                // 盈亏原因
                detail.put("YKYY", getStringValue(bvo.getVnotebody()));
                // 客户编码
                detail.put("KHID", transferCodeByPk(CustomerVO.getDefaultTableName(), CustomerVO.CODE, CustomerVO.PK_CUSTOMER, bvo.getCasscustid()));
                // 供应商编码
                detail.put("GYSID", transferCodeByPk(SupplierVO.getDefaultTableName(), SupplierVO.CODE, SupplierVO.PK_SUPPLIER, bvo.getCvendorid()));
                details.add(detail);
            }
        }
        requestData.put("DETAILS", details);
        requestBody.put("KCPD", requestData);

        return requestBody;
    }

    /**
     * 安全获取字符串值，防止空指针异常
     */
    private String getStringValue(Object value) {
        return value == null ? "" : value.toString();
    }


    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();
    }
}
