using DataLinkMesWork;
using MesServerWork;
using MisDataFunDll;
using MisDataSaveDate.MOM;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.HSSF.Record.Chart;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using static MisDataSaveDate.Helper.ApiLogHelper;
using MisDataSaveDate.Helper;


namespace WebApi
{
    public class CALL_Inerface_DataHandle
    {
        private static bool TryCheckProcessReportAllowed(string opName, string engineID, string orderForm, string reqType)
        {
            DataTable isSendDT = MisDataFun.IOT_ReqData_UpLoad_IsSend(opName, orderForm, reqType, engineID);
            if (isSendDT.Rows[0]["result"].ToString() != "1")
            {
                SaveMesLog($"工序{reqType}", isSendDT.Rows[0]["msg"].ToString(), MesLogType.ERROR);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 开工（工序）
        /// </summary>
        /// <param name="OpName"></param>
        /// <param name="EngineID"></param>
        /// <param name="OrderForm"></param>
        public static void CALL_Inerface_JobStart(string OpName, string EngineID, string OrderForm)
        {
            if (!TryCheckProcessReportAllowed(OpName, EngineID, OrderForm, "开工"))
            {
                return;
            }

            //查询工单ID、任务ID、工序ID
            var param = new SqlParameter[] {
                        new SqlParameter("@订单号",OrderForm),
                        new SqlParameter("@工序号",OpName),
                        new SqlParameter("@工件编号",EngineID)
                    };
            DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobStart", ref param, out DataTable dt, out string errorMessage);

            if (dt.Rows.Count > 0)
            {
                JobStart ReqEntity = new JobStart
                {
                    //orderID = dt.Rows[0]["订单ID"].ToString(),
                    taskID = dt.Rows[0]["任务ID"].ToString(),
                    processId = dt.Rows[0]["工序ID"].ToString(),
                    operationTime = DateTime.Now.ToString(),
                    createTime = DateTime.Now.ToString(),
                    lastModifiedTime = DateTime.Now.ToString(),
                    operation = "1"  //0取消，1开工
                };
                string lineType = ConfigurationManager.AppSettings["WebapiPostHeader_Systemcode"];
                if (lineType == "MES_ZHDQ_126GLKG") ReqEntity.operatorName = "AC09MES";
                if (lineType == "MES_ZHDQ_126DLQ") ReqEntity.operatorName = "AC06MES";
                if (lineType == "MES_ZHDQ_126ZZ") ReqEntity.operatorName = "AC11MES";
                if (OpName == "AC2401") ReqEntity.operatorName = "AC24MES";
                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_ProcessJobStart"];

                var result = CALL_Interface_WebAPI.CALL_WebApi_JobStart(InterfaceUrl, ReqEntity);
                //保存日志
                SaveLog_Interface_Request("CALL_WebApi_JobStart", 1, JsonConvert.SerializeObject(ReqEntity), out int AID);
                SaveLog_Interface_Response(result.ToString(), AID);

                //当上报失败时，保存上报内容至缓存表
                bool reqIsOk = true;
                if (result["code"].ToString() != "200")
                {
                    MisDataFun.CallWebApi_FactoryMes_NGRecordSave("CALL_WebApi_JobStart", AID, InterfaceUrl, JsonConvert.SerializeObject(ReqEntity), result.ToString());
                    // 设置报工状态
                    reqIsOk = false;
                    SaveMesLog(OpName, $"工序开工上报失败：订单号={OrderForm}, 工件编号={EngineID}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
                }
                else
                {
                    SaveMesLog(OpName, $"工序开工上报成功：订单号={OrderForm}, 工件编号={EngineID}", MesLogType.INFO);
                }
                // 保存报工状态
                MisDataFun.IOT_Data_UpLode_Res_Save(OpName, OrderForm, EngineID, "开工", reqIsOk, result.ToString());
            }
            else
            {
                SaveLog_Interface_Request("CallWebApi_FactoryMes_JobStart", 1, $"查询记录数为0：订单号={OrderForm},工序号={OpName},产品流水号={EngineID}", out int AID);
                SaveMesLog(OpName, $"工序开工查询记录数为0：订单号={OrderForm}, 工件编号={EngineID}", MesLogType.WARNING);
            }
        }
        /// <summary>
        /// 完工
        /// </summary>
        /// <param name="OpName"></param>
        /// <param name="EngineID"></param>
        /// <param name="OrderForm"></param>
        public static void CALL_Inerface_JobFinished(string OpName, string EngineID, string OrderForm)
        {
            if (!TryCheckProcessReportAllowed(OpName, EngineID, OrderForm, "完工"))
            {
                return;
            }

            //查询工单ID、任务ID、工序ID
            var param = new SqlParameter[] {
                        new SqlParameter("@订单号",OrderForm),
                        new SqlParameter("@工序号",OpName),
                        new SqlParameter("@工件编号",EngineID)
                    };
            //DataAccess.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobFinished", ref param, out DataSet ds);
            DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobFinished", ref param, out DataSet ds, out string errorMessage);
            //a.[订单ID],[任务ID],[工序ID],[工序名称],1 as 完工数量,@开工时间 as 开工时间,@结束时间 as 结束时间,@节拍 as 节拍,@操作时间 as 最后修改时间
            if (ds.Tables[0].Rows.Count > 0)
            {
                //1、工单信息
                DataRow orderRow = ds.Tables[0].Rows[0];
                JobFinished ReqEntity = new JobFinished
                {
                    //orderID = orderRow["订单ID"].ToString(),
                    taskID = orderRow["任务ID"].ToString(),
                    processNo = orderRow["工序编号"].ToString(),
                    beat = decimal.Parse(orderRow["节拍"].ToString()),
                    finishedQuantity = 1.0M,//完工数量
                    createTime = orderRow["开工时间"].ToString(),
                    endTime = orderRow["结束时间"].ToString(),
                    lastModifiedTime = DateTime.Now.ToString(),
                };
                //2、检验信息，根据质量数据和检验模板生成
                if (ds.Tables[1].Rows.Count > 0)
                {
                    var qualityOK = ds.Tables[1].Rows[0]["是否合格"].ToString();
                    var OKCount = qualityOK == "1" ? 1.0M : 0.0M;
                    var NGCount = qualityOK == "1" ? 0.0M : 1.0M;

                    List<InspectionInfo> inspInfoList = new List<InspectionInfo>();
                    InspectionInfo inspInfo = new InspectionInfo();
                    string lineType = ConfigurationManager.AppSettings["WebapiPostHeader_Systemcode"];
                    if (lineType == "MES_ZHDQ_126GLKG") inspInfo.inspector = "AC09MES";
                    if (lineType == "MES_ZHDQ_126DLQ") inspInfo.inspector = "AC06MES";
                    if (lineType == "MES_ZHDQ_126ZZ") inspInfo.inspector = "AC11MES";
                    if (OpName == "AC2401") inspInfo.inspector = "AC24MES";
                    inspInfo.qualifiedQuantity = OKCount;
                    inspInfo.unqualifiedQuantity = NGCount;
                    inspInfo.inspectionTime = DateTime.Now.ToString();

                    List<InspectionDetail> inspectionDetails = new List<InspectionDetail>();
                    foreach (DataRow inspRow in ds.Tables[1].Rows)
                    {
                        InspectionDetail inspectionDetail = new InspectionDetail();
                        var qualityOKStr = "";
                        string TagValue = inspRow["TagValue"].ToString();
                        if (inspRow["检测结果"].ToString() == "1") qualityOKStr = "合格";
                        else qualityOKStr = inspRow["检测结果"].ToString() == "0" ? "未测量" : "不合格";

                        // 合格项目 使用 合格不合格
                        if (inspRow["测量单位"]?.ToString() == "OK/NG")
                        {
                            switch (TagValue?.ToString())
                            {
                                case ("1"):
                                    TagValue = "合格";
                                    break;
                                case ("2"):
                                    TagValue = "不合格";
                                    break;
                                case ("0"):
                                    TagValue = "未测量";
                                    break;
                                default:
                                    TagValue = "未知";
                                    break;
                            }
                        }
                        //inspectionDetail.inspectionItemName = inspRow["质检项目名称"].ToString();
                        inspectionDetail.inspectionItemName = inspRow["质检项目名称"].ToString();
                        inspectionDetail.inspectionValue = TagValue;
                        inspectionDetail.inspectionResult = qualityOKStr;
                        inspectionDetail.upperLimitValue = Convert.ToDecimal(inspRow["上限值"]);
                        inspectionDetail.lowerLimitValue = Convert.ToDecimal(inspRow["下限值"]);
                        inspectionDetail.standardValue = Convert.ToDecimal(inspRow["理论值"]);
                        inspectionDetail.upperLimitSymbol = inspRow["测量单位"].ToString();
                        inspectionDetail.lowerLimitSymbol = inspRow["测量单位"].ToString();
                        inspInfo.templetecode = inspRow["模板编号"].ToString();
                        inspectionDetail.inspectionItemID = inspRow["检验项目ID"].ToString();
                        inspectionDetail.inspectionItemNo = inspRow["检验项目编号"].ToString();
                        inspectionDetails.Add(inspectionDetail);
                    }
                    inspInfo.inspectionDetails = inspectionDetails;
                    inspInfoList.Add(inspInfo);
                    ReqEntity.inspectionInfo = inspInfoList;
                }

                List<MaterialInfo> materialInfoList = new List<MaterialInfo>();

                //3、消耗物料信息
                if (ds.Tables[2].Rows.Count > 0)
                {
                    foreach (DataRow MRow in ds.Tables[2].Rows)
                    {
                        MaterialInfo materialInfo = new MaterialInfo();
                        materialInfo.consumedMaterialNo = MRow["物料代码"].ToString();
                        materialInfo.type = "0";
                        materialInfo.qty = 1;
                        materialInfo.batchNo = MRow["物料批次号"].ToString();
                        materialInfo.serialNo = MRow["物料流水号"].ToString();
                        materialInfoList.Add(materialInfo);
                    }
                }

                // 最后再记录一条产出
                MaterialInfo materialInfo2 = new MaterialInfo();
                materialInfo2.consumedMaterialNo = orderRow["产品编号"].ToString();
                materialInfo2.serialNo = EngineID;
                materialInfo2.type = "1";
                materialInfo2.qty = 1;
                materialInfo2.batchNo = "";
                materialInfoList.Add(materialInfo2);
                ReqEntity.materialInfo = materialInfoList;

                //4、工时信息
                List<Workinghours> workinghoursList = new List<Workinghours>();
                Workinghours workinghours = new Workinghours();
                workinghours.workingHours = Math.Round(ReqEntity.beat / 3600, 2);//将秒换算成小时
                workinghours.quantity = 1.0M;
                workinghours.operation = "1";//默认1完工  0 取消完工  1 完工
                workinghoursList.Add(workinghours);
                ReqEntity.workinghours = workinghoursList;

                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_ProcessJobFinish"];
                var result = CALL_Interface_WebAPI.CALL_WebApi_JobFinished(InterfaceUrl, ReqEntity);
                SaveLog_Interface_Request("CALL_WebApi_JobFinish", 1, JsonConvert.SerializeObject(ReqEntity), out int AID);
                SaveLog_Interface_Response(result.ToString(), AID);
                bool reqIsOk = true;
                //当上报失败时，保存上报内容至缓存表
                if (result["code"].ToString() != "200")
                {
                    MisDataFun.CallWebApi_FactoryMes_NGRecordSave("CALL_WebApi_JobFinished", AID, InterfaceUrl, JsonConvert.SerializeObject(ReqEntity), result.ToString());
                    // 设置报工状态
                    reqIsOk = false;
                    SaveMesLog(OpName, $"工序完工上报失败：订单号={OrderForm}, 工件编号={EngineID}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
                }
                else
                {
                    SaveMesLog(OpName, $"工序完工上报成功：订单号={OrderForm}, 工件编号={EngineID}", MesLogType.INFO);
                }
                // 保存报工状态
                MisDataFun.IOT_Data_UpLode_Res_Save(OpName, OrderForm, EngineID, "完工", reqIsOk, result.ToString());
            }
            else
            {
                SaveLog_Interface_Request("CallWebApi_FactoryMes_JobFinish", 1, $"查询记录数为0：订单号={OrderForm},工序号={OpName},产品流水号={EngineID}", out int AID);
                SaveMesLog(OpName, $"工序完工查询记录数为0：订单号={OrderForm}, 工件编号={EngineID}", MesLogType.WARNING);
            }
        }
        /// <summary>
        /// 产线报警信息上报
        /// </summary>
        /// <param name="OpName"></param>
        /// <param name="TagID"></param>
        /// <param name="alarmtype"></param>
        /// <param name="alarmContext"></param>
        public static void CALL_Inerface_DeviceAlarm(string OpName, string TagID, string alarmtype, string alarmContext)
        {
            MIS_BASE.Read_EngineGetOver_PLC(OpName, out bool isWorking);
            if (!isWorking) return; // 没有产品 则不上传数据

            //查询工单ID、任务ID、工序ID
            var param = new SqlParameter[] {
                        new SqlParameter("@工序号",OpName)
                    };
            string orderID = "";
            string taskID = "";
            DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_DeviceAlarm", ref param, out DataTable dt, out string errMessage);
            if (dt.Rows.Count > 0)
            {
                orderID = dt.Rows[0]["订单ID"].ToString();
                taskID = dt.Rows[0]["任务ID"].ToString();
            }
            // 非工厂下发的订单产品，不上传报警
            if (string.IsNullOrEmpty(orderID) || string.IsNullOrEmpty(taskID)) return;

            DeviceAlarm ReqEntity = new DeviceAlarm
            {
                id = Guid.NewGuid().ToString(),
                orderID = orderID,
                taskID = taskID,
                processNo = OpName,
                alarmCode = TagID,
                deviceInfo = alarmContext,
                exceptionInfo = alarmContext,
                exceptionType = alarmtype,
                createTime = DateTime.Now.ToString(),
                lastModifiedTime = DateTime.Now.ToString()
            };
            string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_AlarmInfoUpload"];
            var result = CALL_Interface_WebAPI.CALL_WebApi_DeviceAlarm(InterfaceUrl, ReqEntity);

            SaveLog_Interface_Request("CALL_WebApi_DeviceAlarm", 1, JsonConvert.SerializeObject(ReqEntity), out int AID);
            SaveLog_Interface_Response(result.ToString(), AID);
            //当上报失败时，保存上报内容至缓存表
            if (result["code"].ToString() != "200")
            {
                MisDataFun.CallWebApi_FactoryMes_NGRecordSave("CALL_WebApi_DeviceAlarm", AID, InterfaceUrl, JsonConvert.SerializeObject(ReqEntity), result.ToString());
                SaveMesLog(OpName, $"设备报警上报失败：报警代码={TagID}, 报警内容={alarmContext}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
            }
            else
            {
                SaveMesLog(OpName, $"设备报警上报成功：报警代码={TagID}, 报警类型={alarmtype}", MesLogType.INFO);
            }

        }
        /// <summary>
        /// 叫料、退料、退空、转序、下空、上空、点对点
        /// </summary>
        /// <param name="PositionCode"></param>
        /// <param name="deliveryType">1退托盘，2叫料，3送料，4转序，5下空，6上空，7点对点</param>
        /// <summary>
        /// 叫料、退料、退空、转序、下空、上空、点对点
        /// </summary>
        /// <param name="PositionCode"></param>
        /// <param name="deliveryType">1退托盘，2叫料，3送料，4转序，5下空，6上空，7点对点</param>
        public static bool CALL_Inerface_CallMaterial(string PositionCode, string deliveryType)
        {
            // 配送类型映射：1退托盘，2叫料，3送料，4转序，5下空，6上空，7点对点
            Dictionary<string, string> deliveryTypeMap = new Dictionary<string, string>
            {
                { "1", "退托盘" },
                { "2", "叫料" },
                { "3", "送料" },
                { "4", "转序" },
                { "5", "下空" },
                { "6", "上空" },
                { "7", "点对点" }
            };
            string deliveryTypeName = deliveryTypeMap.ContainsKey(deliveryType) ? deliveryTypeMap[deliveryType] : "未知";

            //查询工单ID、任务ID、工序ID
            var param = new SqlParameter[] {
                        new SqlParameter("@位置号",PositionCode),
                        new SqlParameter("@叫料类型",deliveryType)
                    };
            DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_CallMaterial", ref param, out DataTable dt, out string errMessage);
            if (dt.Rows.Count > 0)
            {
                string containerNo = "";
                if (deliveryType == "1")
                {
                    // 获取器具号（318）
                    containerNo = MIS_BASE.ReadPLC(318, PositionCode).ToString();
                }

                var callMaterialCode = Guid.NewGuid().ToString();
                MaterialSend ReqEntity = new MaterialSend
                {
                    code = callMaterialCode,
                    orderID = dt.Rows[0]["派工单ID"].ToString(),
                    taskID = dt.Rows[0]["taskId"].ToString(),
                    sequenceNo = dt.Rows[0]["顺序号"].ToString(),
                    deliveryType = deliveryType,
                    processStep = dt.Rows[0]["工序号"].ToString(),
                    startLocation = (deliveryType == "1" || deliveryType == "3" || deliveryType == "4" || deliveryType == "5" || deliveryType == "7") ? PositionCode : "",
                    endLocation = (deliveryType == "2" || deliveryType == "6") ? PositionCode : "",
                    material = dt.Rows[0]["物料号"].ToString(),
                    quantity = Convert.ToInt32(dt.Rows[0]["数量"]),
                    trayNumber = containerNo, //dt.Rows[0]["托盘号"].ToString(),
                    prodline = "", // 产线
                    workstation = "",
                    workshop = "",
                    customerid = "",
                    creator = "Auto",
                    createTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    lastModifiedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };
                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_CallMaterial"];
                SaveLog_Interface_Request("CallWebApiUrl_CallMaterial", 1, JsonConvert.SerializeObject(ReqEntity), out int AID);
                var result = CALL_Interface_WebAPI.CALL_WebApi_CallMaterial(InterfaceUrl, ReqEntity);
                SaveLog_Interface_Response(result.ToString(), AID);
                //当上报失败时，保存上报内容至缓存表
                if (result["code"].ToString() != "200")
                {
                    var param1 = new SqlParameter[] {
                        new SqlParameter("@接口名称","CallWebApiUrl_CallMaterial"),
                        new SqlParameter("@接口地址",InterfaceUrl),
                        new SqlParameter("@请求内容",JsonConvert.SerializeObject(ReqEntity)),
                        new SqlParameter("@响应内容",result.ToString())
                    };
                    DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_NGRecordSave", ref param1, out string errMessage1);
                    SaveMesLog(PositionCode, $"叫料上报失败：配送类型={deliveryType}({deliveryTypeName}), 起始位置={ReqEntity.startLocation}, 终点位置={ReqEntity.endLocation}, 物料号={ReqEntity.material}, 叫料任务号={callMaterialCode}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
                    return false;
                }
                else
                {
                    SaveMesLog(PositionCode, $"叫料上报成功：配送类型={deliveryType}({deliveryTypeName}), 起始位置={ReqEntity.startLocation}, 终点位置={ReqEntity.endLocation}, 物料号={ReqEntity.material}, 叫料任务号={callMaterialCode}", MesLogType.INFO);
                }
                MisDataFun.Location_MIS_MOBY_Insert(PositionCode, "器具号", ReqEntity.trayNumber);
                MisDataFun.Location_MIS_MOBY_Insert(PositionCode, "叫料任务号", callMaterialCode);
                MisDataFun.Location_MIS_MOBY_Insert(PositionCode, "派工单ID", dt.Rows[0]["派工单ID"].ToString());
                MisDataFun.Location_MIS_MOBY_Insert(PositionCode, "派工任务ID", dt.Rows[0]["taskId"].ToString());
                MisDataFun.Location_MIS_MOBY_Insert(PositionCode, "订单号", dt.Rows[0]["订单号"].ToString());

                var param2 = new SqlParameter[] {
                        new SqlParameter("@叫料任务号",ReqEntity.code),
                        new SqlParameter("@派工单ID",ReqEntity.orderID),
                        new SqlParameter("@派工任务ID",ReqEntity.taskID),
                        new SqlParameter("@顺序号",ReqEntity.sequenceNo),
                        new SqlParameter("@配送类型",ReqEntity.deliveryType),
                        new SqlParameter("@工序",ReqEntity.processStep),
                        new SqlParameter("@起始位置编号",ReqEntity.startLocation),
                        new SqlParameter("@终点位置编号",ReqEntity.endLocation),
                        new SqlParameter("@配送物料编码",ReqEntity.material),
                        new SqlParameter("@配送数量",ReqEntity.quantity),
                        new SqlParameter("@器具号",ReqEntity.trayNumber),
                        new SqlParameter("@创建人编号",ReqEntity.creator),
                        new SqlParameter("@创建时间",ReqEntity.createTime),
                        new SqlParameter("@最后修改时间",ReqEntity.lastModifiedTime),
                    };
                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("MOM_生产任务_派工任务_叫料记录_增加", ref param2, out string errMessage2);
            }
            else
            {
                SaveLog_Interface_Request("CallWebApi_FactoryMes_DeviceAlarm", 1, $"查询记录数为0：工序号={PositionCode}", out int AID);
                SaveMesLog(PositionCode, $"叫料查询记录数为0：配送类型={deliveryType}({deliveryTypeName})", MesLogType.WARNING);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 物料配送确认
        /// </summary>
        /// <param name="PositionCode">位置号</param>
        /// <param name="containerNo">器具号</param>
        public static bool CALL_Inerface_MaterialConfirm(string PositionCode, string containerNo)
        {
            try
            {
                // 调用存储过程获取叫料任务号和派工任务ID
                var param = new SqlParameter[] {
            new SqlParameter("@位置号", PositionCode),
            new SqlParameter("@器具号", containerNo)
        };

                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("MOM_生产任务_派工任务_叫料记录_到料确认", ref param, out DataTable dtResult, out string errMessage);

                if (dtResult == null || dtResult.Rows.Count == 0)
                {
                    SaveLog_Interface_Request("CallWebApiUrl_MaterialInfoConfirm", 0,
                        $"获取叫料记录失败：位置号={PositionCode}, 器具号={containerNo}, 错误信息={errMessage}", out int errorAID);
                    SaveMesLog(PositionCode, $"物料配送确认-获取叫料记录失败：器具号={containerNo}, 错误={errMessage}", MesLogType.ERROR);
                    return false;
                }

                // 获取存储过程返回的数据
                string tackcode = dtResult.Rows[0]["叫料任务号"].ToString();
                string taskID = dtResult.Rows[0]["派工任务ID"].ToString();

                MaterialConfirm materialConfirm = new MaterialConfirm
                {
                    tackcode = tackcode, // 从存储过程获取的配送任务号
                    orderID = "", // 派工单ID
                    taskID = taskID, // 从存储过程获取的派工任务ID
                    processId = PositionCode, // 工序ID
                    containerNo = containerNo // 器具号
                };

                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_MaterialInfoConfirm"];
                var result = CALL_Interface_WebAPI.CALL_WebApi_MaterialConfirm(InterfaceUrl, materialConfirm);
                SaveLog_Interface_Request("CallWebApiUrl_MaterialInfoConfirm", 1, JsonConvert.SerializeObject(materialConfirm), out int AID);
                SaveLog_Interface_Response(result.ToString(), AID);

                //当上报失败时，保存上报内容至缓存表
                if (result["code"].ToString() != "200")
                {
                    var param1 = new SqlParameter[] {
                new SqlParameter("@接口名称","CallWebApiUrl_MaterialInfoConfirm"),
                new SqlParameter("@接口地址",InterfaceUrl),
                new SqlParameter("@请求内容",JsonConvert.SerializeObject(materialConfirm)),
                new SqlParameter("@响应内容",result.ToString())
            };
                    DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_NGRecordSave", ref param1, out string errMessage1);
                    SaveMesLog(PositionCode, $"物料配送确认上报失败：器具号={containerNo}, 叫料任务号={tackcode}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
                    return false;
                }
                SaveMesLog(PositionCode, $"物料配送确认上报成功：器具号={containerNo}, 叫料任务号={tackcode}", MesLogType.INFO);
                return true;
            }
            catch (Exception ex)
            {
                SaveLog_Interface_Request("CallWebApiUrl_MaterialInfoConfirm", 0,
                    $"物料配送确认异常：{ex.Message}", out int exceptionAID);
                SaveMesLog("MOM", $"物料配送确认异常：位置号={PositionCode}, 器具号={containerNo}, 异常={ex.Message}", MesLogType.ERROR);
                return false;
            }
        }


        /// <summary>
        /// 器具信息查询
        /// </summary>
        /// <param name="PositionCode">位置号</param>        
        /// <param name="containerNo">托盘号</param>
        /// <returns>器具信息查询结果</returns>
        public static DeviceInfoResponse CALL_Inerface_DeviceInfoQuery(string PositionCode, string containerNo)
        {
            // 通过位置号查询任务号
            var param = new SqlParameter[] {
                        new SqlParameter("@位置号",PositionCode)
                    };
            DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("MOM_生产任务_派工任务_叫料记录_器具查询", ref param, out DataTable dt, out string errMessage);

            if (dt.Rows.Count > 0)
            {
                string taskId = dt.Rows[0]["任务号"].ToString();

                DeviceInfo deviceInfo = new DeviceInfo
                {
                    id = taskId, // 使用查询出的任务号
                    callcode = "",
                    containerNo = containerNo
                };

                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_DeviceInfoQuery"];
                SaveLog_Interface_Request("CallWebApiUrl_DeviceInfoQuery", 1, JsonConvert.SerializeObject(deviceInfo), out int AID);
                var result = CALL_Interface_WebAPI.CALL_WebApi_DeviceInfoQuery(InterfaceUrl, deviceInfo);
                SaveLog_Interface_Response(result.ToString(), AID);

                // 解析返回结果
                DeviceInfoResponse response = JsonConvert.DeserializeObject<DeviceInfoResponse>(result.ToString());

                //当上报失败时，保存上报内容至缓存表
                if (result["code"].ToString() != "200")
                {
                    var param1 = new SqlParameter[] {
                            new SqlParameter("@接口名称","CallWebApiUrl_DeviceInfoQuery"),
                            new SqlParameter("@接口地址",InterfaceUrl),
                            new SqlParameter("@请求内容",JsonConvert.SerializeObject(deviceInfo)),
                            new SqlParameter("@响应内容",result.ToString())
                        };
                    DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_NGRecordSave", ref param1, out string errMessage1);
                    SaveMesLog(PositionCode, $"器具信息查询失败：位置号={PositionCode}, 器具号={containerNo}, 任务号={taskId}, 返回码={result["code"]}, 消息={result["message"]}", MesLogType.ERROR);
                }
                else
                {
                    SaveMesLog(PositionCode, $"器具信息查询成功：位置号={PositionCode}, 器具号={containerNo}, 任务号={taskId}", MesLogType.INFO);
                }

                return response;
            }
            else
            {
                SaveLog_Interface_Request("CALL_Inerface_DeviceInfoQuery", 1, $"查询记录数为0：位置号={PositionCode}", out int AID);

                // 返回空结果
                return new DeviceInfoResponse
                {
                    code = 404,
                    message = $"查询记录数为0：位置号={PositionCode}",
                    data = null
                };
            }
        }

        /// <summary>
        /// 物料转序
        /// </summary>
        /// <param name="startPositionCode">起始位置编号</param>
        /// <param name="endPositionCode">终点位置编号</param>
        /// <param name="dataid">派工任务id</param>
        /// <param name="moveTaskType">搬运类型：1：搬运容器，2：搬运货架</param>
        /// <param name="vehicleStatus">载具类型：0-空；1-满</param>
        /// <returns>返回调用结果 JObject，包含 code 和 message</returns>
        public static JObject CALL_Inerface_MaterialTransfer(string startPositionCode, string endPositionCode, string dataid = "", string moveTaskType = "2", string vehicleStatus = "1")
        {
            JObject response = new JObject();
            try
            {
                // 根据起止库位号前缀（前6位）查询任务模板编号
                var paramTaskType = new SqlParameter[] {
                    new SqlParameter("@起始库位号", startPositionCode ?? ""),
                    new SqlParameter("@结束库位号", endPositionCode ?? "")
                };
                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("XD_AGV任务模板_获取", ref paramTaskType, out DataTable dtTaskType, out string errTaskType);

                if (!string.IsNullOrEmpty(errTaskType) || dtTaskType == null || dtTaskType.Rows.Count == 0
                    || string.IsNullOrWhiteSpace(dtTaskType.Rows[0]["任务模板编号"]?.ToString()))
                {
                    string errorMsg = $"未找到匹配的任务模板：起点={startPositionCode}, 终点={endPositionCode}";
                    if (!string.IsNullOrEmpty(errTaskType))
                    {
                        errorMsg += $", 错误={errTaskType}";
                    }
                    SaveMesLog("MOM", $"物料转序失败：{errorMsg}", MesLogType.ERROR);

                    response["code"] = 500;
                    response["message"] = errorMsg;
                    return response;
                }

                string taskType = dtTaskType.Rows[0]["任务模板编号"].ToString();

                // 构建位置列表
                List<PositionInfo> positionList = new List<PositionInfo>
        {
            new PositionInfo
            {
                type = "00", // 工位
                positionCode = startPositionCode
            },
            new PositionInfo
            {
                type = "00", // 工位
                positionCode = endPositionCode
            }
        };

                MaterialTransfer ReqEntity = new MaterialTransfer
                {
                    reqCode = Guid.NewGuid().ToString(),
                    reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    clientCode = "126GIS",
                    taskType = taskType,
                    moveTaskType = moveTaskType,
                    vehicleStatus = vehicleStatus,
                    positionCodeList = positionList,
                    dataid = dataid
                };

                string InterfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_MaterialTransfer"];
                SaveLog_Interface_Request("CALL_WebApi_MaterialTransfer", 1, JsonConvert.SerializeObject(ReqEntity), out int AID);
                var result = CALL_Interface_WebAPI.CALL_WebApi_MaterialTransfer(InterfaceUrl, ReqEntity);
                SaveLog_Interface_Response(result.ToString(), AID);

                //当上报失败时，保存上报内容至缓存表
                if (result["code"].ToString() != "200")
                {
                    var param1 = new SqlParameter[] {
                new SqlParameter("@接口名称","CALL_WebApi_MaterialTransfer"),
                new SqlParameter("@接口地址",InterfaceUrl),
                new SqlParameter("@请求内容",JsonConvert.SerializeObject(ReqEntity)),
                new SqlParameter("@响应内容",result.ToString())
            };
                    DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_NGRecordSave", ref param1, out string errMessage1);

                    string errorMsg = result["message"]?.ToString() ?? "未知错误";
                    SaveMesLog("MOM", $"物料转序上报失败：起点={startPositionCode}终点={endPositionCode}, 返回码={result["code"]}, 消息={errorMsg}", MesLogType.ERROR);

                    response["code"] = result["code"];
                    response["message"] = errorMsg;
                }
                else
                {
                    SaveMesLog("MOM", $"物料转序上报成功：起点={startPositionCode}终点={endPositionCode}", MesLogType.INFO);
                    response["code"] = 200;
                    response["message"] = "AGV调度成功";
                }
            }
            catch (Exception ex)
            {
                SaveLog_Interface_Request("CALL_WebApi_MaterialTransfer", 0,
                    $"物料转序异常：{ex.Message}", out int exceptionAID);
                SaveMesLog("MOM", $"物料转序异常：起点={startPositionCode}终点={endPositionCode}, 异常={ex.Message}", MesLogType.ERROR);

                response["code"] = 500;
                response["message"] = $"物料转序异常：{ex.Message}";
            }
            return response;
        }

        /// <summary>
        /// 点检结果上传
        /// </summary>
        /// <param name="reqEntity">点检结果实体</param>
        /// <returns>工厂MES响应</returns>
        public static JObject CALL_Inerface_SpotCheckResultUpload(SpotCheckResult reqEntity)
        {
            try
            {
                if (reqEntity == null)
                {
                    SaveMesLog("MOM", "点检结果上传失败：点检结果不能为空", MesLogType.ERROR);
                    throw new ArgumentNullException(nameof(reqEntity), "点检结果不能为空");
                }

                if (reqEntity.ResultData == null || reqEntity.ResultData.Count == 0)
                {
                    SaveMesLog("MOM", "点检结果上传失败：点检结果缺少明细数据", MesLogType.ERROR);
                    throw new Exception("点检结果缺少明细数据");
                }

                string interfaceUrl = ConfigurationManager.AppSettings["CallWebApiUrl_SpotCheckRecordCreate"];
                if (string.IsNullOrWhiteSpace(interfaceUrl))
                {
                    SaveMesLog("MOM", "点检结果上传失败：未配置 CallWebApiUrl_SpotCheckRecordCreate", MesLogType.ERROR);
                    throw new Exception("未配置 CallWebApiUrl_SpotCheckRecordCreate");
                }

                string requestName = "CALL_WebApi_SpotCheckRecordCreate";
                string requestBody = JsonConvert.SerializeObject(reqEntity);
                SaveLog_Interface_Request(requestName, 1, requestBody, out int AID);

                var result = CALL_Interface_WebAPI.CALL_WebApi_SpotCheckRecord(interfaceUrl, reqEntity);
                SaveLog_Interface_Response(result.ToString(), AID);

                var codeToken = result["code"];
                if (codeToken == null || codeToken.ToString() != "200")
                {
                    MisDataFun.CallWebApi_FactoryMes_NGRecordSave(requestName, AID, interfaceUrl, requestBody, result.ToString());

                    string errorMsg = result["message"]?.ToString() ?? "未知错误";
                    string code = codeToken?.ToString() ?? "null";
                    SaveMesLog("MOM", $"点检结果上报失败：返回码={code}, 消息={errorMsg}", MesLogType.ERROR);
                }
                else
                {
                    SaveMesLog("MOM", "点检结果上报成功", MesLogType.INFO);
                }

                return result;
            }
            catch (Exception ex)
            {
                SaveMesLog("MOM", $"点检结果上传异常：{ex.Message}", MesLogType.ERROR);
                throw;
            }
        }

        //#region 西开 AGV 发送方法 (MES -> AGV)

        ///// <summary>
        ///// 下发任务给 AGV
        ///// MES 调用 AGV 接口，下发搬运任务
        ///// </summary>
        ///// <param name="requestTaskId">任务唯一ID（由调用方生成，如 Guid）</param>
        ///// <param name="startPosition">抬货点/取货位置</param>
        ///// <param name="endPosition">卸货点/目标位置</param>
        ///// <param name="materialCode">产品编码/物料编码</param>
        ///// <returns>AGV 响应结果</returns>
        //public static JObject CALL_ZZAGV_AddTask(string requestTaskId, string startPosition, string endPosition, string materialCode)
        //{
        //    JObject response = new JObject();
        //    try
        //    {
        //        // 参数校验
        //        if (string.IsNullOrWhiteSpace(requestTaskId))
        //        {
        //            requestTaskId = Guid.NewGuid().ToString();
        //        }

        //        if (string.IsNullOrWhiteSpace(startPosition))
        //        {
        //            throw new ArgumentException("抬货点(startPosition)不能为空");
        //        }

        //        if (string.IsNullOrWhiteSpace(endPosition))
        //        {
        //            throw new ArgumentException("卸货点(endPosition)不能为空");
        //        }

        //        // 构建请求实体
        //        var reqEntity = new MisDataSaveDate.ZZAGV_AddTaskRequest
        //        {
        //            requestTaskId = requestTaskId,
        //            startPosition = startPosition,
        //            endPosition = endPosition,
        //            materialCode = materialCode ?? ""
        //        };

        //        // 获取 AGV 接口地址
        //        string baseUrl = ConfigurationManager.AppSettings["ZZAGV_BaseUrl"];
        //        if (string.IsNullOrWhiteSpace(baseUrl))
        //        {
        //            throw new Exception("未配置 ZZAGV_BaseUrl");
        //        }
        //        string interfaceUrl = baseUrl.TrimEnd('/') + "/api/mes/AddTaskFromMes";

        //        string jsonStr = JsonConvert.SerializeObject(reqEntity);
        //        SaveLog_Interface_Request("CALL_ZZAGV_AddTask", 1, jsonStr, out int AID);

        //        // 发送 HTTP 请求
        //        string resultStr = "";
        //        try
        //        {
        //            resultStr = WebApi.Post.Post_Auto(interfaceUrl, jsonStr);
        //        }
        //        catch (Exception httpEx)
        //        {
        //            SaveMesLog("ZZAGV", $"下发任务HTTP请求异常：起点={startPosition}, 终点={endPosition}, 异常={httpEx.Message}", MesLogType.ERROR);
        //            SaveLog_Interface_Response($"HTTP请求异常：{httpEx.Message}", AID);
        //            response["code"] = 500;
        //            response["desc"] = $"HTTP请求异常：{httpEx.Message}";
        //            response["success"] = false;
        //            return response;
        //        }

        //        SaveLog_Interface_Response(resultStr, AID);

        //        // 解析响应
        //        if (string.IsNullOrWhiteSpace(resultStr))
        //        {
        //            SaveMesLog("ZZAGV", "下发任务失败：AGV返回空响应", MesLogType.ERROR);
        //            response["code"] = 500;
        //            response["desc"] = "AGV返回空响应";
        //            response["success"] = false;
        //            return response;
        //        }

        //        response = JObject.Parse(resultStr);

        //        // 检查返回码
        //        string code = response["code"]?.ToString();
        //        if (code != "0")
        //        {
        //            string desc = response["desc"]?.ToString() ?? "未知错误";
        //            SaveMesLog("ZZAGV", $"下发任务失败：任务ID={requestTaskId}, 起点={startPosition}, 终点={endPosition}, 返回码={code}, 消息={desc}", MesLogType.ERROR);

        //            // 保存失败记录
        //            MisDataFun.CallWebApi_FactoryMes_NGRecordSave("CALL_ZZAGV_AddTask", AID, interfaceUrl, jsonStr, resultStr);
        //        }
        //        else
        //        {
        //            SaveMesLog("ZZAGV", $"下发任务成功：任务ID={requestTaskId}, 起点={startPosition}, 终点={endPosition}", MesLogType.INFO);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        SaveMesLog("ZZAGV", $"下发任务异常：{ex.Message}", MesLogType.ERROR);
        //        response["code"] = 500;
        //        response["desc"] = $"异常：{ex.Message}";
        //        response["success"] = false;
        //    }

        //    return response;
        //}

        ///// <summary>
        ///// 放行 AGV
        ///// MES 调用 AGV 接口，告知 AGV 可以离开当前位置
        ///// </summary>
        ///// <param name="requestId">请求ID</param>
        ///// <param name="position">当前位置编号</param>
        ///// <returns>AGV 响应结果</returns>
        //public static JObject CALL_ZZAGV_AllowLeave(string requestId, string position)
        //{
        //    JObject response = new JObject();
        //    try
        //    {
        //        // 参数校验
        //        if (string.IsNullOrWhiteSpace(requestId))
        //        {
        //            requestId = Guid.NewGuid().ToString();
        //        }

        //        if (string.IsNullOrWhiteSpace(position))
        //        {
        //            throw new ArgumentException("位置编号(position)不能为空");
        //        }

        //        // 构建请求实体
        //        var reqEntity = new MisDataSaveDate.ZZAGV_AllowLeaveRequest
        //        {
        //            requestId = requestId,
        //            position = position,
        //            allowLeave = 1
        //        };

        //        // 获取 AGV 接口地址
        //        string baseUrl = ConfigurationManager.AppSettings["ZZAGV_BaseUrl"];
        //        if (string.IsNullOrWhiteSpace(baseUrl))
        //        {
        //            throw new Exception("未配置 ZZAGV_BaseUrl");
        //        }
        //        string interfaceUrl = baseUrl.TrimEnd('/') + "/api/mes/AllowLeave";

        //        string jsonStr = JsonConvert.SerializeObject(reqEntity);
        //        SaveLog_Interface_Request("CALL_ZZAGV_AllowLeave", 1, jsonStr, out int AID);

        //        // 发送 HTTP 请求
        //        string resultStr = "";
        //        try
        //        {
        //            resultStr = WebApi.Post.Post_Auto(interfaceUrl, jsonStr);
        //        }
        //        catch (Exception httpEx)
        //        {
        //            SaveMesLog("ZZAGV", $"放行AGV HTTP请求异常：位置={position}, 异常={httpEx.Message}", MesLogType.ERROR);
        //            SaveLog_Interface_Response($"HTTP请求异常：{httpEx.Message}", AID);
        //            response["code"] = 500;
        //            response["desc"] = $"HTTP请求异常：{httpEx.Message}";
        //            response["success"] = false;
        //            return response;
        //        }

        //        SaveLog_Interface_Response(resultStr, AID);

        //        // 解析响应
        //        if (string.IsNullOrWhiteSpace(resultStr))
        //        {
        //            SaveMesLog("ZZAGV", "放行AGV失败：AGV返回空响应", MesLogType.ERROR);
        //            response["code"] = 500;
        //            response["desc"] = "AGV返回空响应";
        //            response["success"] = false;
        //            return response;
        //        }

        //        response = JObject.Parse(resultStr);

        //        // 检查返回码
        //        string code = response["code"]?.ToString();
        //        if (code != "0")
        //        {
        //            string desc = response["desc"]?.ToString() ?? "未知错误";
        //            SaveMesLog("ZZAGV", $"放行AGV失败：请求ID={requestId}, 位置={position}, 返回码={code}, 消息={desc}", MesLogType.ERROR);

        //            // 保存失败记录
        //            MisDataFun.CallWebApi_FactoryMes_NGRecordSave("CALL_ZZAGV_AllowLeave", AID, interfaceUrl, jsonStr, resultStr);
        //        }
        //        else
        //        {
        //            SaveMesLog("ZZAGV", $"放行AGV成功：请求ID={requestId}, 位置={position}", MesLogType.INFO);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        SaveMesLog("ZZAGV", $"放行AGV异常：{ex.Message}", MesLogType.ERROR);
        //        response["code"] = 500;
        //        response["desc"] = $"异常：{ex.Message}";
        //        response["success"] = false;
        //    }

        //    return response;
        //}

        //#endregion
    }
}
