using DbCommon.BusinessCore.BaseCore;
using DbCommon.Extenions;
using Pms.DataLibrary.Models;
using Pms.DataLibrary.Order;
using Pms.Models;
using Pms.WebHandle;
using ProjectManagementSystem.Common.Log;
using ProjectManagementSystem.Common.WebApi;
using ProjectManagementSystem.NHibernateDBHelper;
using ProjectManagementSystem.WebApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ProjectManagementSystem.TaskEvent
{
    public abstract class CTaskEventBase
    {
        
        protected LocationPropertyManager m_locationManager = new LocationPropertyManager();
        private Dictionary<string, TaskData> TaskDataDict { get; set; } = new Dictionary<string, TaskData>();
        public CTaskEventBase()
        {
            Task.Factory.StartNew(TaskThread);
        }

        private List<TaskData> GetTaskDataList()
        {
            if (!PmsApi.Get(EPmsApi.GetTaskList, null, null, out List<TaskData> taskDataList)) return null;
            foreach (var item in taskDataList)
            {
                if (!PmsApi.Get(EPmsApi.GetStepList, new { TaskID = item.TaskID }, null, out List<StepData> stepInfoList))
                {
                    return null;
                }
                item.StepList = stepInfoList;
            }
            return taskDataList;
        }

        private TaskData GetTaskData(string taskId)
        {
            if (!PmsApi.Get(EPmsApi.GetTask, new { TaskID = taskId }, null, out TaskData taskData)) return null;
            if (!PmsApi.Get(EPmsApi.GetStepList, new { TaskID = taskId }, null, out List<StepData> stepInfoList)) return null;

            taskData.StepList = stepInfoList;
            return taskData;
        }

        private void TaskEventProc()
        {
            var taskDataList = GetTaskDataList();
            MiddleOrderDataStateProc(taskDataList);
            //var taskDataList1 = GetTaskDataList();
            return;//暂时后面用不到

            if (taskDataList == null) return;

            TaskStateProc(taskDataList);
            TaskDynamicRely(taskDataList);
        }

        private void MiddleOrderDataStateProc(List<TaskData> taskDataList)
        {
            #region 更新任务状态
            try
            {
                using (var session = MiddleDBModelHelper.Session)
                {
                    var result = session.QueryOver<Order>().Where(p => p.OrderState <=8).List();
                    foreach (var order in result)
                    {
                        if (order.CallTime.AddSeconds(1) > DateTime.Now)
                        {
                            break;
                        }
                        if (taskDataList != null && taskDataList.Count > 0)
                        {
                            var pmsResut = taskDataList.FindAll(p => p.TaskID == order.OrderID);//&& (p.TaskState != ETaskState.Exception || p.TaskState != ETaskState.Exceptioned)
                            if (pmsResut != null && pmsResut.Count > 0)
                            {
                                var p = pmsResut[0];
                                if(p.TaskState==ETaskState.Exception || p.TaskState == ETaskState.Exceptioned || p.TaskState == ETaskState.Canceled)
                                {
                                    if (order.OrderState != 8)
                                    {
                                        order.OrderState = 8;
                                        order.Suspend = false;
                                    }

                                }
                                //else if(p.TaskState == ETaskState.Finished)
                                //{
                                //    order.OrderState = 7;
                                //}
                                if (order.Carrier != p.Carrier)
                                {
                                    order.Carrier = p.Carrier;
                                    order.OrderState = 2;
                                    order.Suspend = false;
                                }
                                session.Update(order);
                            }
                            else
                            {
                                if((order.FinishTime == DateTime.MaxValue && order.OrderState != 7) ||(order.Suspend&&order.OrderState>=7))
                                {
                                    session.Delete(order);
                                    continue;
                                }
                            }
                        }
                        else if (taskDataList != null && taskDataList.Count == 0)
                        {
                            if ((order.FinishTime == DateTime.MaxValue && order.OrderState != 7) || (order.Suspend && order.OrderState >= 7))
                            {
                                session.Delete(order);
                                continue;
                            }
                            //session.Delete(order);
                            //continue;
                        }
                        if (!order.Suspend)
                        {
                            string[] values = order.OrderID.Split('_');
                            string tempOrderId = values != null & values.Length > 1 ? values[1] : order.OrderID;
                            TaskState taskState = new TaskState();
                            taskState.taskid = tempOrderId;
                            taskState.taskstate = order.OrderState;
                            taskState.agvid = GlobalData.GetSKCarrier(order.Carrier).ToString();
                            taskState.faultcode = 0;//
                            taskState.updatetime = DateTime.Now.ToString("G");
                            TaskStateResponse taskStateResponse = SKMESWebServiceHelper.UpdateTaskState(taskState);
                            if (taskStateResponse != null && taskStateResponse.code == "0")
                            {
                                order.Suspend = true;
                                session.Update(order);
                            }
                        }
                    }
                    session.Flush();
                }
            }
            catch (Exception ex)
            {
                //TextDocument.WriteFile(@"PMS/Log","更新中间表任务状态", ex.ToString());
            }
            #endregion
        }
        private void TaskStateProc(List<TaskData> taskDataList)
        {

            #region YYY
            // 当前任务更新到缓存
            foreach (var taskData in taskDataList)
            {
                if (!TaskDataDict.ContainsKey(taskData.ID))
                {
                    TaskDataDict.Add(taskData.ID, taskData);
                    CLog.Instance.GetLog("Task").WriteDebug($"{taskData.TaskID} 任务状态{taskData.TaskState}(添加记录) {taskData.ID} ");
                }
                else
                {
                    var lastTaskInfo = TaskDataDict[taskData.ID];
                    if (lastTaskInfo.TaskState != taskData.TaskState)
                    {
                        CLog.Instance.GetLog("Task").WriteDebug($"{taskData.TaskID} 运行状态改变 {lastTaskInfo.TaskState} => {taskData.TaskState}");
                        TaskStateChanged(taskData, lastTaskInfo);
                    }
                    TaskDataDict[taskData.ID] = taskData;
                }
            }

            //获取历史任务对比
            if (TaskDataDict.Count == 0) { return; }
            string[] taskIdArray = TaskDataDict.Keys.ToArray();
            foreach (string id in taskIdArray)
            {
                if (PmsApi.Get(EPmsApi.GetHistoryTask, new { TaskID = TaskDataDict[id].TaskID }, null, out TaskData taskData)
                    && taskData != null
                    && taskData.ID == id
                    && TaskDataDict.ContainsKey(id))
                {
                    CLog.Instance.GetLog("Task").WriteDebug($"{TaskDataDict[id].TaskID} 任务状态{taskData.TaskState}(移除记录) {id}");
                    TaskDataDict.Remove(id);
                    switch (taskData.TaskState)
                    {
                        case ETaskState.Finished:
                            TaskFinished(taskData);
                            break;
                        case ETaskState.Canceled:
                            TaskCanceled(taskData);
                            break;
                        case ETaskState.Exceptioned:
                            TaskExceptioned(taskData);
                            break;
                        case ETaskState.RecoveryException:
                            break;
                        default:
                            break;
                    }
                }
            }
            #endregion
        }

        /// <summary>
        /// 动态自动续接任务（通过Excel配置的任务依赖）
        /// </summary>
        private void TaskDynamicRely(List<TaskData> taskDataList)
        {
            var taskIds = taskDataList.Where(d => d.TaskState == ETaskState.Add)
                .Select(d => d.TaskID)
                .ToArray();

            foreach (var taskId in taskIds)
            {
                //重新获取当前所有任务
                var taskDataListTemp = GetTaskDataList();
                if (taskDataListTemp == null) continue;

                var taskData = taskDataListTemp.FirstOrDefault(d => d.TaskID == taskId);
                if (taskData == null) continue;

                string parentId = GetParentTaskId(taskData, taskDataListTemp, out string currentWhouse, out string relayLastWhouse, out int carrier);
                if (parentId != taskData.ParentTaskID)
                {
                    RequestTaskStep requestTaskStep = new RequestTaskStep()
                    {
                        TaskID = taskData.TaskID,
                        ParentTaskID = parentId
                    };

                    bool result = PmsApi.Post(EPmsApi.TaskChangeRely, null, requestTaskStep, out RequestTaskStep taskStep);
                    CLog.Instance.GetLog("Task").WriteInfo($"{taskData.TaskID} 更改父任务{result.ToChineseString()} {taskData.ParentTaskID} => {parentId}" +
                        (string.IsNullOrEmpty(parentId) ? string.Empty : $"（{carrier}# {relayLastWhouse} 前往续接 {currentWhouse}）"));
                }
            }
        }

        private string GetParentTaskId(TaskData taskData, List<TaskData> taskDataList, out string currentWhouse, out string relayLastWhouse, out int carrier)
        {
            currentWhouse = null;
            relayLastWhouse = null;
            carrier = 0;

            //从配置表中获取当前任务的第一个点可以续接哪些库位
            string firstPos = taskData.StepList.OrderBy(d => d.StepID).FirstOrDefault()?.WareHouseID;
            string firstWhouse = m_locationManager.QueryWareHouse(firstPos);
            var taskRely = Common.Config.ExcelConfig.Instance.TaskRelyList.FirstOrDefault(f => f.StartWareHouse == firstWhouse);
            if (taskRely == null) return string.Empty;

            //获取已经被续接的任务号
            var parentTaskList = taskDataList.Where(d => !string.IsNullOrEmpty(d.ParentTaskID)).ToList();

            var task = taskDataList
                .Where(d =>
                {
                    //已经续接过的任务不能用
                    var parentTask = parentTaskList.FirstOrDefault(f => f.ParentTaskID == d.TaskID);
                    if (parentTask != null)
                    {
                        if (parentTask.TaskID != taskData.TaskID)
                        {
                            return false;
                        }
                    }

                    //查找已开始任务
                    if (d.TaskState <= ETaskState.Add) return false;

                    //AGV类型需要一致
                    if (d.CarrierType != taskData.CarrierType) return false;

                    //临近任务结束
                    if (d.StepList.Count - d.CurrentStepID > 3) return false;

                    string lastPos = d.StepList.OrderByDescending(f => f.StepID).FirstOrDefault()?.WareHouseID;
                    string lastWhouse = m_locationManager.QueryWareHouse(lastPos);
                    d.reserved1 = lastWhouse;

                    return taskRely.EndWareHouse.Contains(lastWhouse);
                })
                .OrderBy(d =>
                {
                    return d.StepList.Count - d.CurrentStepID;//依据任务离最后一步的步骤数量进行排序
                })
                .FirstOrDefault();


            if (task != null)
            {
                currentWhouse = firstWhouse;
                relayLastWhouse = task.reserved1;
                carrier = task.Carrier;
            }

            return (task == null) ? string.Empty : task.TaskID;
        }

        public void TaskThread()
        {
            while (true)
            {
                try
                {
                    TaskEventProc();
                }
                catch (Exception ex)
                {
                    CLog.Instance.GetLog("Task").WriteException("Exception", ex);
                }
                Thread.Sleep(60);
            }
        }

        public abstract void TaskStateChanged(TaskData currentTaskInfo, TaskData lastTaskInfo);
        public abstract void TaskFinished(TaskData taskInfo);
        public abstract void TaskExceptioned(TaskData taskInfo);
        public abstract void TaskCanceled(TaskData taskInfo);
    }
}

