using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyLog4Net;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Web.Http;
using MesServerWork;
using MesDataFunction;
using System.IO;
using System.Configuration;
using Org.BouncyCastle.Ocsp;
using System.Threading;

namespace MisDataSaveDate
{
    public class WebSendServer
    {
        private static readonly string ImageShareBasePath = ConfigurationManager.AppSettings["ImageShareBasePath"];
        private static readonly string ImageShareUser = ConfigurationManager.AppSettings["ImageShareUser"];
        private static readonly string ImageSharePassword = ConfigurationManager.AppSettings["ImageSharePassword"];

        /// <summary>
        /// MES接口重试
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ApiFailRetry(string url, [FromBody] JObject jobj)
        {
            var result = new msgResHeader2();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("MES接口重试_res", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            var req = JsonConvert.DeserializeObject<ApiFailRetryData>(str);
            string opName = req.OpName.Trim();
            string type = req.Type.Trim().ToLowerInvariant();

            try
            {
                if (req == null)
                {
                    throw new Exception("请求体解析失败！");
                }
                result.MsgId = req.MsgId ?? "";

                if (string.IsNullOrWhiteSpace(req.OpName))
                {
                    throw new Exception("参数OpName为空！");
                }
                if (string.IsNullOrWhiteSpace(req.Type))
                {
                    throw new Exception("参数Type为空！");
                }

                string functionCode = MIS_BASE.hashtable_MesDll[opName].ToString();

                // Type -> TagTypeCodeID
                string tagTypeCodeId;

                if (type == "workover")
                {
                    MIS_BASE.Read_MesRead(opName, out bool isMesRead);
                    if(functionCode != "Function1055") // 非拧紧工位需要判断允许保存信号 其他工位不管
                    {
                        if (!isMesRead) throw new Exception("工位未允许保存，不可强制完成！");
                    }
                    else
                    {
                        MIS_BASE.Write_OpNameIsOk(opName, -99); // 先复位报警信号 一秒后 再写入合格 因为如果不合格MES会判定不合格的 拧紧工位PLCS 和 PLC不判定
                        Thread.Sleep(1000);
                    }

                    // 写入当前工位总合格标志为不合格 走不合格放行
                    MIS_BASE.Write_TagValueByTagTypeID(51, opName, false); // 合格放行
                    MIS_BASE.Write_TagValueByTagTypeID(8, opName, true); // 不合格放行

                    // 记录不合格过站信息
                    MisDataFunDll.MisDataFun.WorkStartInsert(opName, 2);
                    //通知PLC，MES保存完成
                    MIS_BASE.Write_MesReadOver(opName, true);
                    //通知PLC，MES工作完成
                    MIS_BASE.Write_MesWorkFinish(opName, true);
                    result.Code = "200";
                    result.Message = "强制出站成功";
                    MisDataFunDll.MisDataFun.LogRecording_OP(opName, "WARNING", "MIS", "强制出站成功 强制不合格出站!");
                    return JsonConvert.SerializeObject(result);
                }


                bool workStart,mesRead, engineGetOver_PLC, partLoad, engineTypeGetOverFromMES, fixAllow;
                switch (type)
                {
                    case "mesread":
                        tagTypeCodeId = "19"; // 允许保存
                        MIS_BASE.Read_WorkStart(opName, out workStart);
                        MIS_BASE.Read_MesRead(opName, out mesRead);
                        MIS_BASE.Read_FixAllow(opName, out fixAllow);
                        MIS_BASE.Read_EngineGetOver_PLC(opName, out engineGetOver_PLC);

                        if (!workStart) throw new Exception("当前工位无PLC在位产品 不可触发产品保存!");
                        if (!engineGetOver_PLC) throw new Exception("当前工位未PLC传递机型 不可主动触发传递机型!");
                        if(functionCode != "Function1055")
                        {
                            if(!fixAllow) throw new Exception("当前工位MES未允许工作 不可触发产品保存!"); // 只有非拧紧工位校验
                            if(!mesRead) throw new Exception("当前工位无PLC允许保存信号 不可触发产品保存!"); // 只有非拧紧工位校验
                        }
                        break;
                    case "enginegetover":
                        tagTypeCodeId = "44"; // 传递机型
                        MIS_BASE.Read_WorkStart(opName, out workStart);
                        MIS_BASE.Read_EngineGetOver_PLC(opName, out engineGetOver_PLC);
                        if (!workStart) throw new Exception("当前工位无PLC在位产品 不可触发传递机型!");
                        if (!engineGetOver_PLC) throw new Exception("当前工位未PLC传递机型 不可主动触发传递机型!");
                        break;
                    case "parload":
                    case "partload":
                        tagTypeCodeId = "43"; // 申请上线
                        // 判断是否有申请上线 以及MES的传递机型
                        MIS_BASE.Read_PartLoad(opName, out partLoad);
                        MIS_BASE.Read_EngineTypeGetOver_MES(opName, out engineTypeGetOverFromMES);
                        if (!partLoad) throw new Exception("当前工位PLC未申请上线 不可提前申请!");
                        if(engineTypeGetOverFromMES) throw new Exception("当前工位已获取上线条码并传递 不可重复获取!");
                        break;
                    default:
                        throw new Exception("无效的Type，仅支持: MesRead, MesReadOver, ParLoad");
                }

                // ParLoad 限制
                if (tagTypeCodeId == "43")
                {
                    bool allow = string.Equals(opName, "OP090", StringComparison.OrdinalIgnoreCase)
                               || string.Equals(opName, "OP250", StringComparison.OrdinalIgnoreCase);
                    if (!allow)
                    {
                        throw new Exception("ParLoad 仅允许 OP090 与 OP250 使用！");
                    }
                }

                // 确保 MesDll 映射可用
                if (MIS_BASE.hashtable_MesDll == null || MIS_BASE.hashtable_MesDll.Count == 0)
                {
                    MIS_BASE.InitHashtable_MesServerCode();
                }
                if (!MIS_BASE.hashtable_MesDll.ContainsKey(opName))
                {
                    MIS_BASE.InitHashtable_MesServerCode();
                    if (!MIS_BASE.hashtable_MesDll.ContainsKey(opName))
                    {
                        throw new Exception("工位未配置 MesDll，无法路由到对应Function！");
                    }
                }

                // 取 TagID（若无则回退到 "1"）
                string tagKey = $"{opName}_{tagTypeCodeId}";
                string tagId = null;
                if (MIS_BASE.hashtable_TagTypeID_OpName_ToTagID != null)
                {
                    tagId = MIS_BASE.hashtable_TagTypeID_OpName_ToTagID.Get(tagKey);
                }
                if (string.IsNullOrWhiteSpace(tagId)) tagId = "1";

                // 计算 cmd 名称（用于消息第二段）
                string cmdName = null;
                if (MIS_BASE.hashtable_TagTypeTagName != null)
                {
                    cmdName = MIS_BASE.hashtable_TagTypeTagName.Get(tagTypeCodeId);
                }
                if (string.IsNullOrWhiteSpace(cmdName))
                {
                    cmdName = tagTypeCodeId == "19" ? "MesRead" : tagTypeCodeId == "44" ? "EngineGetOver" : "s";
                }

                // 构建 PLC 源事件并路由
                var eObj = new
                {
                    OpName = opName,
                    TagTypeCodeID = tagTypeCodeId,
                    TagType = tagTypeCodeId,
                    TagID = tagId,
                    TagValue = "1"
                };
                string payload = JsonConvert.SerializeObject(eObj);
                string msg = $"PLC|{cmdName}|{opName}|{payload}";

                MisDataFunDll.MisDataFun.TransferInfToMES(msg);

                result.Code = "200";
                result.Message = "重试触发成功";
                MisDataFunDll.MisDataFun.LogRecording_OP(opName, "WARNING", "MIS", $"{payload}重试触发成功!");
            }
            catch (Exception err)
            {
                MisDataFunDll.MisDataFun.LogRecording_OP(opName, "ERROR", "MIS", $"手动重试失败 {err}");
                result.Code = "500";
                result.Message = err.Message;
            }

            string ret = JsonConvert.SerializeObject(result);
            MyLogHelper.Info("MES接口重试_res", ret);
            return ret;
        }

        /// <summary>
        /// 首件测试数据上传
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string FirstProductUpLoad(string url, [FromBody] JObject jobj)
        {
            var result = new msgResHeader2();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";
            string errorMessage = "";
            int AID = -1;

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("MES接口重试_res", retString1);
                return retString1;
            }
            int isError = 0;
            string str = jobj.ToString();
            try
            {
                //存储日志
                var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                //Event_MOM_Log_Insert,@创建时间,@内容
                var param = new SqlParameter[] {
                    new SqlParameter("@接口地址",url),
                    new SqlParameter("@接口类型",2), // 1. 主动调用接口  2. 被调用接口 
                    new SqlParameter("@请求内容",str),
                    new SqlParameter("@请求时间",CreateTime)
                };
                DataLinkMesWork1.DataAccess.ExecuteStoredProcedure("接口_IOT接口交互日志_请求记录", ref param, out DataTable dt, out errorMessage);

                // 解析订单内容，存储数据库，根据实际业务来写
                FirstProductUpLoadReq firstProductUpLoadReq = JsonConvert.DeserializeObject<FirstProductUpLoadReq>(str);
                if (firstProductUpLoadReq.MsgId == "")
                {
                    throw new Exception("参数MsgId为空！");
                }
                result.MsgId = firstProductUpLoadReq.MsgId;
                if (firstProductUpLoadReq.OpName == "")
                {
                    throw new Exception("参数OpName为空！");
                }

                string OpName = firstProductUpLoadReq.OpName;


                SqlParameter[] param1 = new SqlParameter[1];
                param1[0] = new SqlParameter("@工位号", OpName);
                DataLinkMesWork1.DataAccess.ExecuteStoredProcedure("电子看板_质量数据_首件数据_MOBY_查询", ref param1, out DataTable dt1, out errorMessage);
                if (errorMessage != "")
                {
                    throw new Exception(errorMessage);
                }
                if (dt1.Rows.Count <= 0)
                {
                    throw new Exception(OpName + "首件数据查询为空，无可上传数据！");
                }

                // 这个是首件数据上传接口
                string SOpName = OpName;
                if (OpName == "OP270") SOpName = "OP270-1";
                if (OpName == "OP440") SOpName = "OP440-1";
                if (OpName == "OP490") SOpName = "OP490-1";

                CallWebService.Call_dataCollectForResourceInspect(SOpName, dt1, out string code, out string message);
                if (code == "0")
                {
                    SqlParameter[] param2 = new SqlParameter[1];
                    param2[0] = new SqlParameter("@工位号", OpName);
                    DataLinkMesWork1.DataAccess.ExecuteStoredProcedure("电子看板_质量数据_首件数据_moby_数据转移", ref param2, out DataTable dt2, out errorMessage);
                    if (errorMessage != "")
                    {
                        throw new Exception("首件数据上传成功！数据转移失败！" + errorMessage);
                    }
                    result.Code = "200";
                    result.Message = "首件数据上传成功！";
                }
                else
                {
                    throw new Exception("首件数据上传失败！原因：" + message);
                }
            }
            catch (Exception err)
            {
                result.Code = "500";
                result.Message = err.Message;
            }
            string retString = JsonConvert.SerializeObject(result);
            MyLogHelper.Info("首件数据上传_res", retString);
            return retString;
        }

        /// <summary>
        /// 前端主动触发设备报警
        /// </summary>
        /// <param name="url"></param>
        /// <param name="jobj"></param>
        /// <returns></returns>
        public static string TriggerDeviceAlarm(string url, [FromBody] JObject jobj)
        {
            var result = new msgResHeader2();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";
            string opName = "";

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("前端触发设备报警_res", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            try
            {
                TriggerDeviceAlarmReq req = JsonConvert.DeserializeObject<TriggerDeviceAlarmReq>(str);
                if (req == null)
                {
                    throw new Exception("请求体解析失败！");
                }
                if (string.IsNullOrWhiteSpace(req.MsgId))
                {
                    throw new Exception("参数MsgId为空！");
                }
                result.MsgId = req.MsgId;

                if (string.IsNullOrWhiteSpace(req.OpName))
                {
                    throw new Exception("参数OpName为空！");
                }
                if (string.IsNullOrWhiteSpace(req.AlarmText))
                {
                    throw new Exception("参数AlarmText为空！");
                }
                if (string.IsNullOrWhiteSpace(req.AlarmCode))
                {
                    throw new Exception("参数AlarmCode为空！");
                }

                opName = req.OpName.Trim();
                string alarmText = req.AlarmText.Trim();
                string alarmCode = req.AlarmCode.Trim();

                // 记录工位日志
                MisDataFunDll.MisDataFun.LogRecording_OP(opName, "WARNING", "ALARM", $"触发设备报警 AlarmCode={alarmCode} AlarmText={alarmText}");

                // 写入设备报警
                MIS_BASE.Write_MesErrorType(opName, Convert.ToInt32(alarmCode));

                result.Code = "200";
                result.Message = "报警触发成功";
            }
            catch (Exception ex)
            {
                MisDataFunDll.MisDataFun.LogRecording_OP(opName, "ERROR", "ALARM", $"触发设备报警失败 {ex}");
                result.Code = "500";
                result.Message = ex.Message;
            }

            string retString = JsonConvert.SerializeObject(result);
            MyLogHelper.Info("前端触发设备报警_res", retString);
            return retString;
        }

        /// <summary>
        /// 上传图片到网络共享路径
        /// </summary>
        /// <param name="url"></param>
        /// <param name="jobj"></param>
        /// <returns></returns>
        public static string UploadImageToShare(string url, [FromBody] JObject jobj)
        {
            var result = new msgResHeader2();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";
            string errorMessage = "";

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("上传图片到共享路径_res", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            try
            {
                //// 日志记录
                //var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                //var param = new SqlParameter[] {
                //    new SqlParameter("@接口地址",url),
                //    new SqlParameter("@接口类型",2),
                //    new SqlParameter("@请求内容",str),
                //    new SqlParameter("@请求时间",CreateTime)
                //};
                //DataLinkMesWork1.DataAccess.ExecuteStoredProcedure("接口_IOT接口交互日志_请求记录", ref param, out DataTable dt, out errorMessage);

                // 解析请求
                UploadImageToShareReq req = JsonConvert.DeserializeObject<UploadImageToShareReq>(str);
                if (req == null)
                {
                    throw new Exception("请求体解析失败！");
                }
                if (string.IsNullOrWhiteSpace(req.MsgId))
                {
                    throw new Exception("参数MsgId为空！");
                }
                result.MsgId = req.MsgId;
                // 两种传参方式：
                // 1) TargetPath + FileName
                // 2) RelativePath（以共享根目录为基准，如 OP120\\2025-08-30\\xxx.png）
                bool hasTargetAndFile = !string.IsNullOrWhiteSpace(req.TargetPath) && !string.IsNullOrWhiteSpace(req.FileName);
                bool hasRelative = !string.IsNullOrWhiteSpace(req.RelativePath);
                if (!hasTargetAndFile && !hasRelative)
                {
                    throw new Exception("参数无效：需提供(TargetPath+FileName)或RelativePath之一！");
                }
                if (string.IsNullOrWhiteSpace(req.ImageBase64))
                {
                    throw new Exception("参数ImageBase64为空！");
                }

                // 兼容 data:image/png;base64,xxx 前缀
                string base64 = req.ImageBase64;
                int commaIndex = base64.IndexOf(",");
                if (base64.Contains("base64") && commaIndex >= 0)
                {
                    base64 = base64.Substring(commaIndex + 1);
                }

                byte[] bytes;
                try
                {
                    bytes = Convert.FromBase64String(base64);
                }
                catch
                {
                    throw new Exception("ImageBase64格式不正确，无法解码！");
                }

                // 目录与文件
                string fullPath = string.Empty;
                if (hasTargetAndFile)
                {
                    string targetDir = req.TargetPath.Trim();
                    string fileName = req.FileName.Trim();
                    foreach (char c in Path.GetInvalidFileNameChars())
                    {
                        if (fileName.Contains(c))
                        {
                            throw new Exception("FileName包含非法字符！");
                        }
                    }
                    fullPath = Path.Combine(targetDir, fileName);
                }
                else
                {
                    // 使用相对路径（相对共享根目录）
                    string relative = req.RelativePath.Trim().Replace('/', '\\');
                    if (Path.IsPathRooted(relative) || relative.Contains(":"))
                    {
                        throw new Exception("RelativePath必须为相对路径，不可包含盘符！");
                    }
                    fullPath = Path.Combine(ImageShareBasePath, relative);
                    // 校验最终文件名
                    string leaf = Path.GetFileName(fullPath) ?? "";
                    foreach (char c in Path.GetInvalidFileNameChars())
                    {
                        if (leaf.Contains(c))
                        {
                            throw new Exception("RelativePath中的文件名包含非法字符！");
                        }
                    }
                }
                string fullDir = Path.GetDirectoryName(fullPath) ?? "";
                if (string.IsNullOrWhiteSpace(fullDir))
                {
                    throw new Exception("TargetPath无效，无法获取目录！");
                }

                // 创建目录（支持UNC）
                // 如果是 UNC 路径，先建立网络连接
                EnsureNetworkConnection(fullDir);
                if (!Directory.Exists(fullDir))
                {
                    Directory.CreateDirectory(fullDir);
                }

                // 写入文件（覆盖或新增）
                File.WriteAllBytes(fullPath, bytes);

                result.Code = "200";
                result.Message = "上传成功";
            }
            catch (Exception ex)
            {
                result.Code = "500";
                result.Message = ex.Message;
            }

            string retString = JsonConvert.SerializeObject(result);
            MyLogHelper.Info("上传图片到共享路径_res", retString);
            return retString;
        }

        /// <summary>
        /// 获取产品生产状态
        /// </summary>
        /// <param name="url"></param>
        /// <param name="jobj"></param>
        /// <returns></returns>
        public static string GetSfcStatusAndOperation(string url, [FromBody] JObject jobj)
        {
            var result = new GetSfcStatusRes();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("获取产品生产状态_res", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            try
            {
                // 日志记录
                var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                var param = new SqlParameter[] {
                    new SqlParameter("@接口地址", url),
                    new SqlParameter("@接口类型", 2),
                    new SqlParameter("@请求内容", str),
                    new SqlParameter("@请求时间", CreateTime)
                };
                DataLinkMesWork1.DataAccess.ExecuteStoredProcedure("接口_IOT接口交互日志_请求记录", ref param, out DataTable dt, out string errorMessage);

                // 解析请求
                GetSfcStatusReq req = JsonConvert.DeserializeObject<GetSfcStatusReq>(str);
                if (req == null)
                {
                    throw new Exception("请求体解析失败！");
                }
                if (string.IsNullOrWhiteSpace(req.MsgId))
                {
                    throw new Exception("参数MsgId为空！");
                }
                result.MsgId = req.MsgId;

                if (string.IsNullOrWhiteSpace(req.Barcode))
                {
                    throw new Exception("参数Barcode为空！");
                }

                string barcode = req.Barcode.Trim();

                // 调用接口
                CallWebService.Call_getSfcStatusAndOperation(barcode, out string statusBO, out string operation, out string productStatus, out string opStation, out string code, out string message);

                // 设置返回结果
                //result.StatusBO = statusBO;
                //result.Operation = operation;
                result.ProductStatus = productStatus;
                result.OpStation = opStation;

                if (code == "0")
                {
                    result.Code = "200";
                    result.Message = "查询成功";
                }
                else
                {
                    result.Code = code;
                    result.Message = message;
                }
            }
            catch (Exception ex)
            {
                result.Code = "500";
                result.Message = ex.Message;
            }

            string retString = JsonConvert.SerializeObject(result);
            MyLogHelper.Info("获取产品生产状态_res", retString);
            return retString;
        }

        /// <summary>
        /// 确保网络共享连接可用（针对 UNC 路径）
        /// </summary>
        /// <param name="uncPath">UNC 路径或普通路径</param>
        private static void EnsureNetworkConnection(string uncPath)
        {
            if (string.IsNullOrWhiteSpace(uncPath) || !uncPath.StartsWith(@"\\"))
            {
                return; // 非 UNC 路径，无需处理
            }

            try
            {
                // 从 UNC 路径中提取服务器和共享名，如 \\server\share
                string[] parts = uncPath.TrimStart('\\').Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length < 2)
                {
                    return; // 无法解析
                }
                string shareRoot = $@"\\{parts[0]}\{parts[1]}";

                // 使用 net use 建立连接（若已存在则会快速返回）
                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "net",
                    Arguments = $"use \"{shareRoot}\" /user:{ImageShareUser} {ImageSharePassword}",
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };
                using (var proc = System.Diagnostics.Process.Start(psi))
                {
                    proc.WaitForExit(5000); // 最多等待 5 秒
                    // 忽略返回码，允许"已连接"等情况
                }
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("EnsureNetworkConnection", $"建立网络连接失败: {ex.Message}");
                // 不抛异常，后续文件操作会给出更具体的错误
            }
        }

        /// <summary>
        /// 获取客户标签码
        /// </summary>
        /// <param name="url"></param>
        /// <param name="jobj"></param>
        /// <returns></returns>
        public static string GetClientTagValue(string url, [FromBody] JObject jobj)
        {
            var result = new GetClientTagValueRes();
            result.MsgId = "";
            result.Message = "";
            result.Code = "200";

            if (jobj == null)
            {
                result.Code = "500";
                result.Message = "参数格式不正确！";
                string retString1 = JsonConvert.SerializeObject(result);
                MyLogHelper.Info("获取客户标签码_res", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            try
            {
                GetClientTagValueReq req = JsonConvert.DeserializeObject<GetClientTagValueReq>(str);
                if (req == null)
                {
                    throw new Exception("请求体解析失败！");
                }
                if (string.IsNullOrWhiteSpace(req.MsgId))
                {
                    throw new Exception("参数MsgId为空！");
                }
                result.MsgId = req.MsgId;

                if (string.IsNullOrWhiteSpace(req.EngineID))
                {
                    throw new Exception("参数EngineID为空！");
                }
                if (string.IsNullOrWhiteSpace(req.OpName))
                {
                    throw new Exception("参数OpName为空！");
                }
                if (req.EngineTypeID <= 0)
                {
                    throw new Exception("参数EngineTypeID无效！");
                }

                string engineID = req.EngineID.Trim();
                int engineTypeID = req.EngineTypeID;
                string opName = req.OpName.Trim();

                string tagValue = MisDataFunDll.MisDataFun.GetMesClientTagValue(opName, engineID, engineTypeID);

                if (string.IsNullOrEmpty(tagValue))
                {
                    result.Code = "500";
                    result.Message = "获取客户标签码失败，无可用客户标签码！";
                }
                else
                {
                    result.Code = "200";
                    result.Message = "获取成功";
                    result.TagValue = tagValue;
                }
            }
            catch (Exception ex)
            {
                result.Code = "500";
                result.Message = ex.Message;
            }

            string retString = JsonConvert.SerializeObject(result);
            return retString;
        }
    }



    public class ApiFailRetryData
    {
        /// <summary>
        /// MsgId
        /// </summary>
        public string MsgId { get; set; } = "";

        public int UserId { get; set; } = 0;

        public string OpName { get; set; }
        public string Type { get; set; }
    }

    public class FirstProductUpLoadReq
    {

        /// <summary>
        /// 唯一Id
        /// </summary>
        public string MsgId { get; set; } = "";
        /// <summary>
        /// 工位号
        /// </summary>
        public string OpName { get; set; }
    }

    public class UploadImageToShareReq
    {
        /// <summary>
        /// 唯一Id
        /// </summary>
        public string MsgId { get; set; } = "";
        /// <summary>
        /// 目标共享目录或完整目录，如 \\Cait-officefile\mes\首件照片\OP120(固定架装配)\2025-08-30
        /// </summary>
        public string TargetPath { get; set; }
        /// <summary>
        /// 文件名，如 20250830-094503.png
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// 相对共享根目录的相对路径，如 OP120(固定架装配)\\2025-08-30\\20250830-094503.png
        /// 与 TargetPath+FileName 二选一
        /// </summary>
        public string RelativePath { get; set; }
        /// <summary>
        /// 图片Base64（可含 data:image/png;base64, 前缀）
        /// </summary>
        public string ImageBase64 { get; set; }
    }

    public class GetSfcStatusReq
    {
        /// <summary>
        /// 唯一Id
        /// </summary>
        public string MsgId { get; set; } = "";
        /// <summary>
        /// 产品条码
        /// </summary>
        public string Barcode { get; set; }
    }

    public class GetSfcStatusRes
    {
        public string MsgId { get; set; } = "";
        public string Code { get; set; } = "200";
        public string Message { get; set; } = "";
        /// <summary>
        /// 状态代码（原始值）
        /// </summary>
        //public string StatusBO { get; set; } = "";
        /// <summary>
        /// 操作编号（原始值）
        /// </summary>
        //public string Operation { get; set; } = "";
        /// <summary>
        /// 产品状态（转换后）
        /// </summary>
        public string ProductStatus { get; set; } = "";
        /// <summary>
        /// 工位号（转换后）
        /// </summary>
        public string OpStation { get; set; } = "";
    }

    public class TriggerDeviceAlarmReq
    {
        /// <summary>
        /// 唯一Id
        /// </summary>
        public string MsgId { get; set; } = "";
        /// <summary>
        /// 工位号，如 OP120
        /// </summary>
        public string OpName { get; set; }
        /// <summary>
        /// 报警文本，如 安灯呼叫报警
        /// </summary>
        public string AlarmText { get; set; }
        /// <summary>
        /// 报警代码，如 10005
        /// </summary>
        public string AlarmCode { get; set; }
    }

    public class GetClientTagValueReq
    {
        /// <summary>
        /// 唯一Id
        /// </summary>
        public string MsgId { get; set; } = "";
        /// <summary>
        /// 产品编号
        /// </summary>
        public string EngineID { get; set; }
        /// <summary>
        /// 产品型号代码
        /// </summary>
        public int EngineTypeID { get; set; }

        /// <summary>
        /// 工位号，如 OP120
        /// </summary>
        public string OpName { get; set; }
    }

    public class GetClientTagValueRes
    {
        public string MsgId { get; set; } = "";
        public string Code { get; set; } = "200";
        public string Message { get; set; } = "";
        /// <summary>
        /// 客户标签码值
        /// </summary>
        public string TagValue { get; set; } = "";
    }
}
