using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ExternalDataSync;
using MesServerWork;
using MisDataSaveDate;
using System.Net.Http;
using System.Web.Http;
using MisDataSaveDate.MOM;
using System.Data.SqlClient;
using static MisDataSaveDate.Helper.ApiLogHelper;
using MisDataSaveDate.Helper;
using WebApi;
using System.Security.Policy;
using System.Data;
using MisDataFunDll;
using System.Reflection.Emit;

namespace MisDataSaveDate
{
    /// <summary>
    /// AGV业务处理类
    /// </summary>
    public class AGV_BusinessLogic
    {
        static string agvBaseUrl = ConfigurationManager.AppSettings["AGV_BaseUrl"];

        /// <summary>
        /// 处理AGV进入请求业务逻辑
        /// </summary>
        /// <param name="url">接口URL</param>
        /// <param name="jobj">AGV请求数据</param>
        /// <returns>处理结果</returns>
        public static string ProcessAGVEnterRequest(string url, [FromBody] JObject jobj)
        {
            var result = new AGV_Response();
            result.code = "0";
            result.message = "";
            result.reqCode = "";
            string errorMessage = "";

            if (jobj == null)
            {
                result.code = "1";
                result.message = "参数格式不正确！";
                result.reqCode = "";
                string retString1 = JsonConvert.SerializeObject(result);
                SaveMesLog("AGV进入请求", "参数格式不正确！", MesLogType.ERROR);
                MyLog4Net.MyLogHelper.Info("AGV请求进入接口res:", retString1);
                return retString1;
            }

            string str = jobj.ToString();
            //存储请求日志
            SaveLog_Interface_Request(url, 2, str, out int AID);

            try
            {
                // 解析AGV请求内容
                AGV_EnterRequest enterRequest = JsonConvert.DeserializeObject<AGV_EnterRequest>(str);

                // 必填字段校验
                if (string.IsNullOrWhiteSpace(enterRequest.reqCode))
                {
                    throw new Exception("请求编号(reqCode)不能为空");
                }

                if (string.IsNullOrWhiteSpace(enterRequest.reqTime))
                {
                    throw new Exception("请求时间戳(reqTime)不能为空");
                }

                if (string.IsNullOrWhiteSpace(enterRequest.currentPositionCode))
                {
                    throw new Exception("当前位置编号(currentPositionCode)不能为空");
                }

                if (string.IsNullOrWhiteSpace(enterRequest.method))
                {
                    throw new Exception("方法名(method)不能为空");
                }

                if (string.IsNullOrWhiteSpace(enterRequest.robotCode))
                {
                    throw new Exception("AGV编号(robotCode)不能为空");
                }

                if (string.IsNullOrWhiteSpace(enterRequest.taskCode))
                {
                    throw new Exception("任务编号(taskCode)不能为空");
                }

                string method = enterRequest.method.Trim().ToLower();
                if (method != "apply" && method != "release" && method != "lower" && method != "raise")
                {
                    throw new Exception($"不支持的method：{enterRequest.method}");
                }

                //enterRequest.currentPositionCode = RemoveTrailingZero(enterRequest.currentPositionCode);

                // 调用存储过程保存AGV请求数据
                var param = new SqlParameter[] {
                    new SqlParameter("@reqCode", enterRequest.reqCode ?? ""),
                    new SqlParameter("@reqTime", enterRequest.reqTime ?? ""),
                    new SqlParameter("@cooX", enterRequest.cooX ?? ""),
                    new SqlParameter("@cooY", enterRequest.cooY ?? ""),
                    new SqlParameter("@currentPositionCode", enterRequest.currentPositionCode ?? ""),
                    new SqlParameter("@data", ""),// enterRequest.data ??
                    new SqlParameter("@mapCode", enterRequest.mapCode ?? ""),
                    new SqlParameter("@mapDataCode", enterRequest.mapDataCode ?? ""),
                    new SqlParameter("@stgBinCode", enterRequest.stgBinCode ?? ""),
                    new SqlParameter("@method", method),
                    new SqlParameter("@podCode", enterRequest.podCode ?? ""),
                    new SqlParameter("@podDir", enterRequest.podDir ?? ""),
                    new SqlParameter("@materialLot", enterRequest.materialLot ?? ""),
                    new SqlParameter("@robotCode", enterRequest.robotCode ?? ""),
                    new SqlParameter("@taskCode", enterRequest.taskCode ?? ""),
                    new SqlParameter("@wbCode", enterRequest.wbCode ?? ""),
                    new SqlParameter("@ctnrCode", enterRequest.ctnrCode ?? ""),
                    new SqlParameter("@ctnrType", enterRequest.ctnrType ?? ""),
                    new SqlParameter("@roadWayCode", enterRequest.roadWayCode ?? ""),
                    new SqlParameter("@seq", enterRequest.seq ?? ""),
                    new SqlParameter("@eqpCode", enterRequest.eqpCode ?? "")
                };

                // 这里定义AGV返回的位置 - 从currentPositionCode获取并去掉尾部_1后缀
                string OpCode = "";
                try
                {
                    // 从请求的currentPositionCode字段获取位置码
                    string currentPositionCode = enterRequest.currentPositionCode?.ToString() ?? "";
                    if (!string.IsNullOrEmpty(currentPositionCode))
                    {
                        // 去掉尾部的_1后缀，保留前面的库位号
                        int lastUnderscoreIndex = currentPositionCode.LastIndexOf('_');
                        if (lastUnderscoreIndex > 0)
                        {
                            OpCode = currentPositionCode.Substring(0, lastUnderscoreIndex);
                        }
                        else
                        {
                            // 如果没有下划线，直接使用原值
                            OpCode = currentPositionCode;
                        }
                    }

                    // 如果从currentPositionCode获取不到，使用wbCode作为备用
                    if (string.IsNullOrEmpty(OpCode))
                    {
                        OpCode = enterRequest.wbCode?.ToString() ?? "";
                    }
                }
                catch (Exception ex)
                {
                    // 解析失败时使用wbCode作为备用
                    OpCode = enterRequest.wbCode?.ToString() ?? "";
                    SaveMesLog("AGV进入请求", $"解析currentPositionCode失败，使用wbCode作为备用：{ex.Message}", MesLogType.WARNING);
                }

                // 跟新Moby表 AGV进入离开、下降举升状态
                MisDataFun.Location_MIS_MOBY_Insert(OpCode, method, "1");

                // 执行存储过程
                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_光栅请求记录_增加", ref param, out errorMessage);

                switch (method)
                {
                    case "apply":
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "inReq", enterRequest.reqCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "inTask", enterRequest.taskCode);
                        MisDataFun.Rrunning_AGV_Arrive(OpCode); // 磨合AGV到达
                        MIS_BASE.WritePLC(301, OpCode, true); // 请求进入
                        SaveMesLog(OpCode, $"AGV请求进入成功：工位{OpCode}", MesLogType.INFO);
                        break;
                    case "release": // 离开在收到后反馈回去 发给PLC
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "outReq", enterRequest.reqCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "outTask", enterRequest.taskCode);
                        MisDataFun.Rrunning_AGV_Leave(OpCode); // 磨合AGV离开
                        // 读取一下上一个请求进入的工件编号~~~ 然后传过去 找对应的
                        //bool agvOutResult = PassAgvInOut(OpCode, "", "release"); // 通知AGV可以离开
                        //if (!agvOutResult)
                        //{
                        //    errorMessage = $"AGV离开通知失败：工位{OpCode}";
                        //    SaveMesLog("AGV进入请求", errorMessage, "error");
                        //}
                        SaveMesLog(OpCode, $"AGV离开通知成功：工位{OpCode}", MesLogType.INFO);
                        MIS_BASE.WritePLC(301, OpCode, false); // 请求进入
                        // AGV已离开 - 通知PLC
                        MIS_BASE.WritePLC(303, OpCode, true);
                        MIS_BASE.WritePLC(302, OpCode, false); // 托盘到位 器具放置完毕 请求扫描器具码
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "AllowAGVLeave", "1");
                        break;
                    case "lower":
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "lowerReq", enterRequest.reqCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "lowerTask", enterRequest.taskCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "当前状态", "AGV请求下降");
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "备注", $"lowerReq={enterRequest.reqCode};lowerTask={enterRequest.taskCode}");
                        MIS_BASE.WritePLC(500, OpCode, true); // AGV请求下降
                        SaveMesLog(OpCode, $"AGV请求下降成功：工位{OpCode}", MesLogType.INFO);
                        break;
                    case "raise":
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "raiseReq", enterRequest.reqCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "raiseTask", enterRequest.taskCode);
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "当前状态", "AGV请求举升");
                        MisDataFun.Location_MIS_MOBY_Insert(OpCode, "备注", $"raiseReq={enterRequest.reqCode};raiseTask={enterRequest.taskCode}");
                        MIS_BASE.WritePLC(501, OpCode, true); // AGV请求举升
                        SaveMesLog(OpCode, $"AGV请求举升成功：工位{OpCode}", MesLogType.INFO);
                        break;
                    default:
                        break;
                }


                if (!string.IsNullOrEmpty(errorMessage))
                {
                    result.code = "500";
                    result.message = "AGV请求处理失败";
                    result.reqCode = enterRequest.reqCode;
                    SaveMesLog("AGV进入请求", errorMessage, MesLogType.ERROR);
                }
                else
                {
                    result.code = "0";
                    result.message = "";
                    result.reqCode = enterRequest.reqCode;
                }
            }
            catch (Exception err)
            {
                // 记录错误日志
                SaveMesLog("AGV进入请求", err.Message, MesLogType.ERROR);

                result.code = "1";
                result.message = err.Message;

                // 尝试从请求中获取reqCode
                try
                {
                    AGV_EnterRequest tempRequest = JsonConvert.DeserializeObject<AGV_EnterRequest>(str);
                    result.reqCode = tempRequest?.reqCode ?? "";
                }
                catch
                {
                    result.reqCode = "";
                }
            }

            string retString = JsonConvert.SerializeObject(result);
            // 存储响应日志
            SaveLog_Interface_Response(retString, AID);
            MyLog4Net.MyLogHelper.Info("AGV请求进入接口res:", retString);
            return retString;
        }

        public static string RemoveTrailingZero(string input)
        {
            if (input != null && input.Contains("-0") && input.Length >= 3)
            {
                int dashIndex = input.LastIndexOf("-0");
                if (dashIndex > 0 && dashIndex == input.Length - 3) // 确保是最后的-0x格式
                {
                    return input.Remove(dashIndex + 1, 1); // 去掉"-0"中的0
                }
            }
            return input;
        }

        /// <summary>
        /// 发送AGV任务继续执行请求（允许进入、离开、下降或举升）
        /// </summary>
        /// <param name="opName">工位号</param>
        /// <param name="engineID">工件编号</param>
        /// <param name="type">任务类型</param>
        /// <returns>操作是否成功</returns>
        public static bool PassAgvInOut(string opName, string engineID, string type)
        {
            try
            {
                // 其实没有用 engineID 这玩意正常本工位获取不到

                // 调用存储过程获取AGV任务数据
                var param = new SqlParameter[] {
                    new SqlParameter("@opName", opName),
                    new SqlParameter("@engineID", engineID),
                    new SqlParameter("@type", type)
                };
                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_允许进入离开_查询", ref param, out DataTable dtResult, out string errMessage);

                if (dtResult == null || dtResult.Rows.Count == 0)
                {
                    SaveMesLog(opName, $"获取AGV任务数据失败：工位号={opName}, 工件编号={engineID}, 任务类型={type}, 错误信息={errMessage}", MesLogType.ERROR);
                    return false;
                }

                // 从数据库获取请求编号和任务号
                string reqCode = dtResult.Rows[0]["reqCode"].ToString();
                string taskCode = dtResult.Rows[0]["taskCode"].ToString();

                // 构造AGV反馈请求对象
                AGV_FeedbackRequest agvFeedbackRequest = new AGV_FeedbackRequest()
                {
                    reqCode = reqCode,
                    taskCode = taskCode
                };

                // 获取AGV接口地址并发送请求
                string interfaceUrl = agvBaseUrl.TrimEnd('/') + "/rcms/services/rest/hikRpcService/continueTask";
                string jsonStr = JsonConvert.SerializeObject(agvFeedbackRequest);

                //存储请求日志
                SaveLog_Interface_Request(interfaceUrl, 1, jsonStr, out int AID);

                string resultStr = "";
                try
                {
                    resultStr = Post.Post_Auto(interfaceUrl, jsonStr);
                }
                catch (Exception httpEx)
                {
                    SaveMesLog(opName, $"AGV接口HTTP请求异常：工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={httpEx.Message}", MesLogType.ERROR);
                    // 存储响应日志
                    SaveLog_Interface_Response($"HTTP请求异常：{httpEx.Message}", AID);
                    return false;
                }

                // 存储响应日志
                SaveLog_Interface_Response(resultStr, AID);

                // 解析响应结果
                if (string.IsNullOrWhiteSpace(resultStr))
                {
                    SaveMesLog(opName, "AGV接口返回空响应", MesLogType.ERROR);
                    return false;
                }

                // 检查是否为Post.Post_Auto返回的错误格式
                try
                {
                    JObject tempResult = JsonConvert.DeserializeObject<JObject>(resultStr);
                    if (tempResult != null && tempResult["code"] != null && tempResult["code"].ToString() == "500")
                    {
                        string errorMsg = tempResult["message"]?.ToString() ?? "HTTP请求异常";
                        SaveMesLog(opName, $"AGV接口HTTP异常：工位号={opName}, 工件编号={engineID}, 任务类型={type}, 错误信息={errorMsg}", MesLogType.ERROR);
                        return false;
                    }
                }
                catch
                {
                    // 如果不是标准JSON格式，继续后续处理
                }

                AGV_Response result = JsonConvert.DeserializeObject<AGV_Response>(resultStr);
                if (result == null)
                {
                    SaveMesLog(opName, "AGV接口返回数据格式错误", MesLogType.ERROR);
                    return false;
                }

                // 检查AGV返回码
                string code = result.code?.ToString();
                if (code != "0")
                {
                    string message = result.message?.ToString() ?? "未知错误";
                    SaveMesLog(opName, $"允许AGV光栅请求失败：工位号={opName}, 工件编号={engineID}, 任务类型={type}, code={code}, message={message}", MesLogType.ERROR);
                    return false;
                }

                // 请求成功后调用存储过程更新送料状态
                var updateParam = new SqlParameter[] {
                    new SqlParameter("@opName", opName),
                    new SqlParameter("@engineID", engineID),
                    new SqlParameter("@reqCode", reqCode),
                    new SqlParameter("@taskCode", taskCode)
                };
                DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_光栅请求记录_允许", ref updateParam, out string updateErrMessage);

                if (!string.IsNullOrEmpty(updateErrMessage))
                {
                    SaveMesLog(opName, $"允许AGV光栅请求失败：工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={updateErrMessage}", MesLogType.ERROR);
                    return false;
                }


                // 根据任务类型进行后续操作
                if (type == "apply")
                {
                    // AGV已进入
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVEnter", "1");
                }
                else if (type == "release")
                {
                    // AGV已离开 - 通知PLC
                    MIS_BASE.WritePLC(301, opName, false); // 请求进入
                    MIS_BASE.WritePLC(303, opName, true);
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVLeave", "1");
                }
                else if (type == "lower")
                {
                    // AGV允许下降
                    MIS_BASE.WritePLC(500, opName, false); // AGV请求下降
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVLower", "1");
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "当前状态", "允许AGV下降");
                }
                else if (type == "raise")
                {
                    // AGV允许举升
                    MIS_BASE.WritePLC(501, opName, false); // AGV请求举升
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVRaise", "1");
                    MisDataFun.Location_MIS_MOBY_Insert(opName, "当前状态", "允许AGV举升");
                }

                SaveMesLog(opName, $"允许AGV光栅请求成功：工件编号={engineID}, 请求编号={reqCode}, 任务号={taskCode}, 工位号={opName}, 任务类型={type}", MesLogType.INFO);
                return true;
            }
            catch (Exception ex)
            {
                SaveMesLog(opName, $"允许AGV光栅请求失败：工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={ex.Message}", MesLogType.ERROR);
                return false;
            }
        }
    }
}

