package nc.bs.ic.m4c.sign.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.material.measdoc.MeasdocVO;
import nc.vo.bd.psn.PsndocVO;
import nc.vo.bd.stordoc.StordocVO;
import nc.vo.ic.m4c.entity.SaleOutBodyVO;
import nc.vo.ic.m4c.entity.SaleOutHeadVO;
import nc.vo.ic.m4c.entity.SaleOutVO;
import nc.vo.org.StockOrgVO;
import nc.vo.pub.BusinessException;
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.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;


/**
 * (前置)销售交货单(BIP无) 推送至MES
 */
public class SalesDeliveryOrderRuleMES implements IRule<SaleOutVO> {
    private static final BaseDAO dao = new BaseDAO();
    // MES系统API接口地址
    private static final String MES_API_URL = "/GTHINKING/AjaxService/N_XSSJJSA/102397002.ashx/SOTH_INSERT";
    // 删除销售交货单接口地址
    private static final String MES_DELETE_API_URL = "/GTHINKING/AjaxService/N_XSSJJSA/102397002.ashx/SOTH_DELETE";
    private static final Log obmlog = Log.getInstance("OALOG");
    IHttpPostOtherSys httpPostOtherSys = NCLocator.getInstance().lookup(IHttpPostOtherSys.class);

    @Override
    public void process(SaleOutVO[] saleOutVOS) {
        try {
            if (saleOutVOS == null || saleOutVOS.length == 0) {
                obmlog.info("SalesDeliveryOrderRuleMES-没有要进行处理的销售交货单");
                return;
            }
            // 检查并筛选组织为电缆的采购收货单
            List<SaleOutVO> filteredSaleOutVOS = checkAndFilterBills(saleOutVOS);
            if (filteredSaleOutVOS.isEmpty()) {
                obmlog.debug("SalesDeliveryOrderRuleMES-没有要进行处理的组织为电缆的需要同步的销售交货单");
                return;
            }
            // 处理每个销售交货单
            for (SaleOutVO saleOutVO : filteredSaleOutVOS) {
                SaleOutHeadVO hvo = (SaleOutHeadVO) saleOutVO.getParentVO();
                SaleOutBodyVO[] bvos = (SaleOutBodyVO[]) saleOutVO.getChildrenVO();
                // 构建要发送的数据
                JSONObject syncData = buildSyncData(hvo, bvos);
                // 每次新增销售交货单之前 先删除 然后再新增
                String orderNo = hvo.getVbillcode();
                boolean flag = deleteSalesDeliveryOrder(orderNo);
                if (flag) {
                    // 发送数据到MES系统
                    obmlog.debug("SalesDeliveryOrderRuleMES-准备发送销售交货单数据: " + hvo.getVbillcode());
                    httpPostOtherSys.sendToExternalSystem(MES_API_URL, syncData);
                }
            }
        } catch (Exception e) {
            obmlog.error("SalesDeliveryOrderRuleMES-处理异常:" + e.getMessage(), e);
            ExceptionUtils.wrappException(e);
        }
    }

    /**
     * 构建符合MES系统接口规范的请求数据
     */
    private JSONObject buildSyncData(SaleOutHeadVO hvo, SaleOutBodyVO[] bvos) throws BusinessException {
        obmlog.debug("SalesDeliveryOrderRuleMES-开始处理销售交货单: " + hvo.getVbillcode());
        JSONObject requestData = new JSONObject();
        JSONObject info = new JSONObject();
        // 主表数据 - 所有字段处理
        // 必填字段
        info.put("orderNo", hvo.getVbillcode());  // 必填：交货单号
        info.put("orderDate", hvo.getDbilldate() == null ? null : hvo.getDbilldate().toString().substring(0, 10));
        info.put("deliveryDate", hvo.getDbilldate() == null ? null : hvo.getDbilldate().toString().substring(0, 10));
        // 客户ID - 订单客户(ccustomerid)
        info.put("customId", transferCodeByPk(CustomerVO.getDefaultTableName(),
                CustomerVO.CODE, CustomerVO.PK_CUSTOMER, hvo.getCcustomerid()));  // 必填：客户编码
        // 开票单位编码
        info.put("invoicingUnit", transferCodeByPk(CustomerVO.getDefaultTableName(), CustomerVO.CODE, CustomerVO.PK_CUSTOMER, hvo.getCcustomervid()));
        // 销售部门编码
        info.put("departmentId", transferCodeByPk(DeptVersionVO.getDefaultTableName(),
                DeptVersionVO.CODE, DeptVersionVO.PK_VID, hvo.getCdptvid()));  // 必填：销售部门编码
        // 销售员
        info.put("seller", transferCodeByPk(PsndocVO.getDefaultTableName(),
                PsndocVO.NAME, PsndocVO.PK_PSNDOC, hvo.getCbizid()));
        info.put("invoicingBasis", "S");  // 必填：开票依据
        info.put("settlementType", "S");  // 必填：结算方式
        // 仓库编码
        info.put("warehouseId", transferCodeByPk(StordocVO.getDefaultTableName(),
                StordocVO.CODE, StordocVO.PK_STORDOC, hvo.getCwarehouseid()));  // 必填：仓库编码
        // 必填：事务类型
        info.put("type", "XSCK");
        // 必填：生成方式
        info.put("genType", "S");
        // 必填：是否退货
        info.put("returned", "N");
        // 非必填字段
        info.put("transportMode", null);  // 运输方式
        info.put("deliveryAddress", null);  // 收货地点
        info.put("contacts", null);  // 联系人
        info.put("contactNum", null);  // 联系电话
        info.put("originalNo", null);  // 原交货单号
        info.put("remark", hvo.getVnote());  // 备注
        info.put("creatorNo", null);  // 维护人工号
        info.put("creator", null);  // 维护人
        info.put("creatTime", null);  // 维护时间
        // 表头字段需要表体字段
        // 必填：汇率
        info.put("exchangeRate", 1);
        // 必填：货币编码
        info.put("currency", "CNY");
        // 构建明细数组
        JSONArray details = new JSONArray();
        if (bvos != null) {
            for (SaleOutBodyVO bvo : bvos) {
                JSONObject detail = new JSONObject();
                // 必填字段
                detail.put("orderNo", hvo.getVbillcode());  // 必填：交货单号
                detail.put("orderSn", bvo.getCrowno());  // 必填：交货单序号
                // 生成方式为按订单时必填
                detail.put("soOrderNo", bvo.getVsourcebillcode());  //  销售订单号
                detail.put("soSequenceNum", bvo.getVsourcerowno());  // 销售订单序号
                // 物料编码
                detail.put("materialId", transferCodeByPk(MaterialVO.getDefaultTableName(),
                        MaterialVO.CODE, MaterialVO.PK_MATERIAL, bvo.getCmaterialoid()));  // 必填：物料编码
                // 计量单位
                detail.put("unit", transferCodeByPk(MeasdocVO.getDefaultTableName(),
                        MeasdocVO.CODE, MeasdocVO.PK_MEASDOC, bvo.getCunitid()));  // 必填：计量单位
                detail.put("scaleFactor", transferSpecialField(bvo.getVchangerate()));  // 必填：换算系数
                detail.put("taxRate", bvo.getNtaxrate().getDouble());  // 必填：税率
                detail.put("recQty", bvo.getNshouldassistnum().getDouble());  // 必填：应收数量
                detail.put("mainRecQty", bvo.getNnum().getDouble());  // 必填：主应收数量
                // 非必填字段
                detail.put("batchNum", null);  // 物料批号
                detail.put("productNum", null);  // 制令号
                detail.put("assitRecQty", null);  // 辅应收数量
                detail.put("priceIncludeTax", null);  // 原币含税价格
                detail.put("amountIncludeTax", null);  // 原币含税金额
                detail.put("taxAmount", null);  // 税额
                detail.put("remark", null);  // 备注
                details.add(detail);
            }
        }
        info.put("Details", details);
        // 将info对象添加到请求数据中
        requestData.put("Data", info);
        return requestData;
    }

    /**
     * 根据主键获取对应的编码
     */
    private String transferCodeByPk(String tableName, String selectField, String pkField, String pk) throws BusinessException {
        if (pk == null || pk.trim().isEmpty()) {
            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();
    }

    /**
     * 删除第三方系统中的销售交货单
     *
     * @param orderNo 要删除的销售交货单号
     * @return 删除操作是否成功
     * @throws BusinessException 业务异常
     */
    public boolean deleteSalesDeliveryOrder(String orderNo) throws BusinessException {
        try {
            if (orderNo == null || orderNo.trim().isEmpty()) {
                throw new BusinessException("销售交货单号不能为空");
            }
            obmlog.debug("SalesDeliveryOrderRuleMES-准备删除第三方系统销售交货单: " + orderNo);
            // 构建请求数据
            JSONObject requestData = new JSONObject();
            JSONObject dataObj = new JSONObject();
            dataObj.put("orderNo", orderNo);
            requestData.put("Data", dataObj);
            // 发送删除请求
            String response = httpPostOtherSys.callMes(MES_DELETE_API_URL, requestData);
            obmlog.debug("SalesDeliveryOrderRuleMES-删除请求返回结果: " + response);
            // 解析返回结果
            JSONObject jsonResponse = JSONObject.parseObject(response);
            boolean isSuccess = jsonResponse.getBooleanValue("Success");
            String errorMessage = jsonResponse.getString("ErrorMessage");
            if (!isSuccess) {
                obmlog.error("SalesDeliveryOrderRuleMES-删除销售交货单失败: " + orderNo + ", 错误信息: " + errorMessage);
                throw new BusinessException("删除销售交货单失败: " + (errorMessage != null ? errorMessage : "未知错误"));
            }
            obmlog.debug("SalesDeliveryOrderRuleMES-成功删除销售交货单: " + orderNo);
            return true;
        } catch (Exception e) {
            obmlog.error("SalesDeliveryOrderRuleMES-删除销售交货单异常:" + e.getMessage(), e);
            throw new BusinessException("删除销售交货单时发生异常: " + e.getMessage(), e);
        }
    }

    /**
     * 检查并筛选需要同步的单据
     */
    private List<SaleOutVO> checkAndFilterBills(SaleOutVO[] saleOutVOS) {
        List<SaleOutVO> result = new ArrayList<>();
        for (SaleOutVO vo : saleOutVOS) {
            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;
    }

    private String transferSpecialField(String field) {
        if (field == null || field.trim().isEmpty()) {
            return null;
        }
        String[] split = field.split("/");
        if (split.length == 2) {
            String numStr = split[0].trim();
            String denStr = split[1].trim();

            if (denStr.equals("0")) {
                return "0.00"; // 分母不能为零
            }

            try {
                BigDecimal numerator = new BigDecimal(numStr);
                BigDecimal denominator = new BigDecimal(denStr);
                return numerator.divide(denominator, 2, RoundingMode.HALF_UP).toString();
            } catch (NumberFormatException e) {
                return field; // 非法数字，返回原字段
            }
        }
        return field;
    }
}
