using MesServerWork;
using MisDataFunDll;
using MisDataSaveDate;
using System;
using System.Collections;

namespace MesServerFunctions
{
    partial class FunctionMES
    {
        /// <summary>
        /// 处理 PAD/MQTT 发送到 Function1062 的 WEB 命令。
        /// 消息外层格式由通讯层统一为：WEB|命令|工位号|参数。
        /// 命令名不增加 OP431 前缀，工位归属统一通过 opName 判断，避免同一业务出现多套命令名。
        /// </summary>
        private void WebSubmit(object e)
        {
            try
            {
                var msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e;
                string opName = Convert.ToString(msgEvent.OpName);
                string content = Convert.ToString(msgEvent.TagValue);

                // Function 入口已将 MQTT 的 Command 和 Value 合并为“命令|参数”。
                // 参数支持“产品码”或“产品码^最小静置分钟数”，订单、机型等业务信息必须由后端重新查询。
                string[] dataArray = content.Split('|');
                if (dataArray.Length != 2)
                {
                    MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", "PAD命令格式错误，内容：" + content);
                    return;
                }

                string command = dataArray[0].Trim();
                string value = dataArray[1].Trim();

                switch (command)
                {
                    // PAD 扫码查询：只查询产品、前序离开时间和静置分钟数，不写 PLC，也不调用工厂 MES 进站。
                    case "PadScanQuery":
                        {
                            if (!TryGetManualStaticPadRequest(opName, "PadScanQuery", value, out string engineID, out decimal minStaticMinutes))
                            {
                                return;
                            }

                            bool success = QueryManualStaticOutProduct(opName, engineID, minStaticMinutes, out string message);
                            SendManualStaticOutResult(opName, "PadScanQuery", success, message);
                            break;
                        }
                    // PAD 确认上线：重新校验托盘到位、PLC申请上线和前端配置的最小静置时间，通过后写 PLC 产品区。
                    case "PadConfirmOnline":
                        {
                            if (!TryGetManualStaticPadRequest(opName, "PadConfirmOnline", value, out string engineID, out decimal minStaticMinutes))
                            {
                                return;
                            }

                            bool success = ConfirmManualStaticOutProduct(opName, engineID, minStaticMinutes, out string message);
                            SendManualStaticOutResult(opName, "PadConfirmOnline", success, message);
                            MisDataFun.LogRecording_OP(opName, success ? "INFO" : "ERROR", "PadConfirmOnline", message);
                            break;
                        }
                    // 页面刷新或 PAD 重新订阅 MQTT 后，用当前 PLC/MES 状态恢复界面显示。
                    case "IniSingalToWeb":
                        InitializeSingalToWeb(opName);
                        break;
                    default:
                        MisDataFun.LogRecording_OP(opName, "WARNING", "WebSubmit", "不支持的PAD命令：" + command);
                        break;
                }
            }
            catch (Exception err)
            {
                MyLog4Net.MyLogHelper.Error("Function1062.WebSubmit", err.Message);
                MisDataFun.LogRecording_OP(ManualStaticOutOpName, "ERROR", "WebSubmit", err.Message);
            }
        }

        /// <summary>
        /// 解析 PAD 命令参数，取得产品码和最小静置分钟数。
        /// </summary>
        private bool TryGetManualStaticPadRequest(string opName, string command, string value, out string engineID, out decimal minStaticMinutes)
        {
            engineID = "";
            minStaticMinutes = DefaultManualStaticMinutes;
            string requestValue = Convert.ToString(value).Trim();

            // PAD 上传产品码和可选最小静置分钟数。订单、机型、静置开始时间等信息全部从 MES 数据库重新取。
            if (string.IsNullOrWhiteSpace(requestValue))
            {
                string message = "PAD命令参数为空，格式：" + command + "|产品码 或 " + command + "|产品码^最小静置分钟数";
                SendManualStaticOutResult(opName, command, false, message);
                MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", message);
                return false;
            }

            if (requestValue.Contains("&"))
            {
                string message = "PAD命令参数格式错误，格式：" + command + "|产品码 或 " + command + "|产品码^最小静置分钟数，收到：" + value;
                SendManualStaticOutResult(opName, command, false, message);
                MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", message);
                return false;
            }

            // 参数最多允许“产品码^最小静置分钟数”两段。
            string[] requestItems = requestValue.Split('^');
            if (requestItems.Length > 2)
            {
                string message = "PAD命令参数格式错误，格式：" + command + "|产品码 或 " + command + "|产品码^最小静置分钟数，收到：" + value;
                SendManualStaticOutResult(opName, command, false, message);
                MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", message);
                return false;
            }

            engineID = requestItems[0].Trim();
            if (string.IsNullOrWhiteSpace(engineID))
            {
                string message = "PAD命令产品码为空，格式：" + command + "|产品码 或 " + command + "|产品码^最小静置分钟数";
                SendManualStaticOutResult(opName, command, false, message);
                MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", message);
                return false;
            }

            if (requestItems.Length == 2)
            {
                // 最小静置分钟数由 PAD 配置传入，未传时使用默认 30 分钟。
                string minStaticMinutesText = requestItems[1].Trim();
                if (!decimal.TryParse(minStaticMinutesText, out minStaticMinutes) || minStaticMinutes < 0)
                {
                    string message = "PAD命令最小静置分钟数无效，收到：" + minStaticMinutesText;
                    SendManualStaticOutResult(opName, command, false, message);
                    MisDataFun.LogRecording_OP(opName, "ERROR", "WEB", message);
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 页面重新登录或 PAD 重新订阅时恢复关键状态。
        /// 这里发送的是通用命令名，工位由 opName 区分。
        /// </summary>
        private void InitializeSingalToWeb(string opName)
        {
            MIS_BASE.GetEngineTypeFromDB(opName, out int engineTypeID, out string engineType, out string engineID, out int partPalletCode);

            MIS_BASE.Read_WorkStart(opName, out bool workStart);
            MIS_BASE.Read_PartLoad(opName, out bool partLoad);
            MIS_BASE.Read_EngineGetOver_PLC(opName, out bool engineGetOver);
            MIS_BASE.Read_FixAllow(opName, out bool fixAllow);
            MIS_BASE.Read_QualityData_Read_CF(opName, out bool mesRead);
            MIS_BASE.Read_MesReadOver(opName, out bool readOver);
            MIS_BASE.Read_MaterialVerifyOver(opName, out bool workFinish);
            MIS_BASE.Read_QualityMask(opName, out int qualityMask);
            MIS_BASE.Read_FalseGo(opName, out bool falseGo);

            if (!string.IsNullOrWhiteSpace(engineID))
            {
                SendMessageFun.SendMessage("5123", "1111", opName);
            }

            // 以下状态沿用通用 MES 页面命令，PAD 或页面通过 opName 判断属于哪个工位。
            SendMessageFun.SendInfomation("WorkStart", Convert.ToString(Convert.ToInt32(workStart)), opName);
            SendMessageFun.SendInfomation("PartLoad", Convert.ToString(Convert.ToInt32(partLoad)), opName);
            SendMessageFun.SendInfomation("EngineTypeGetOverPLC", Convert.ToString(Convert.ToInt32(engineGetOver)), opName);
            SendMessageFun.SendInfomation("FixAllow", Convert.ToString(Convert.ToInt32(fixAllow)), opName);
            SendMessageFun.SendInfomation("MesRead", Convert.ToString(Convert.ToInt32(mesRead)), opName);
            SendMessageFun.SendInfomation("MesReadOver", Convert.ToString(Convert.ToInt32(readOver)), opName);
            SendMessageFun.SendInfomation("MaterialVerifyOver", Convert.ToString(Convert.ToInt32(workFinish)), opName);
            SendMessageFun.SendInfomation("QualityMask", Convert.ToString(qualityMask), opName);
            SendMessageFun.SendInfomation("FalseGO", Convert.ToString(Convert.ToInt32(falseGo)), opName);
            SendMessageFun.SendInfomation("CurrentProduct", engineID + "^" + engineTypeID + "^" + engineType + "^" + partPalletCode, opName);

            InitAlarm(opName);
        }

        /// <summary>
        /// 重新发送当前工位报警状态。
        /// </summary>
        private void InitAlarm(string opName)
        {
            FuntionMesRead.Alarm_InitAlarm_Send(opName, out Hashtable ht);
            foreach (DictionaryEntry kv in ht)
            {
                FuntionMesRead.Send_AlarmMsg(kv.Key.ToString(), kv.Value.ToString());
            }
        }
    }
}
