using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serein.Library.Api;
using Serein.Library.Entity;
using Serein.Library.Enums;
using Serein.Library.Ex;
using Serein.NodeFlow.Tool.SereinExpression;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using static Serein.Library.Utils.ChannelFlowInterrupt;

namespace Serein.NodeFlow.Base
{

    /// <summary>
    /// 节点基类（数据）：条件控件，动作控件，条件区域，动作区域
    /// </summary>
    public abstract partial class NodeModelBase : IDynamicFlowNode
    {


        #region 调试中断


        /// <summary>
        /// 不再中断
        /// </summary>
        public void CancelInterrupt()
        {
            this.DebugSetting.InterruptClass = InterruptClass.None;
            DebugSetting.CancelInterruptCallback?.Invoke();
        }

        #endregion

        #region 导出/导入项目文件节点信息

        internal abstract Parameterdata[] GetParameterdatas();
        internal virtual NodeInfo ToInfo()
        {
            // if (MethodDetails == null) return null;

            var trueNodes = SuccessorNodes[ConnectionType.IsSucceed].Select(item => item.Guid); // 真分支
            var falseNodes = SuccessorNodes[ConnectionType.IsFail].Select(item => item.Guid);// 假分支
            var errorNodes = SuccessorNodes[ConnectionType.IsError].Select(item => item.Guid);// 异常分支
            var upstreamNodes = SuccessorNodes[ConnectionType.Upstream].Select(item => item.Guid);// 上游分支

            // 生成参数列表
            Parameterdata[] parameterData = GetParameterdatas();

            return new NodeInfo
            {
                Guid = Guid,
                MethodName = MethodDetails?.MethodName,
                Label = DisplayName ?? "",
                Type = this.GetType().ToString(),
                TrueNodes = trueNodes.ToArray(),
                FalseNodes = falseNodes.ToArray(),
                UpstreamNodes = upstreamNodes.ToArray(),
                ParameterData = parameterData.ToArray(),
                ErrorNodes = errorNodes.ToArray(),

            };
        }

        internal virtual NodeModelBase LoadInfo(NodeInfo nodeInfo)
        {
            var node = this;
            if (node != null)
            {
                node.Guid = nodeInfo.Guid;
                for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
                {
                    Parameterdata? pd = nodeInfo.ParameterData[i];
                    node.MethodDetails.ExplicitDatas[i].IsExplicitData = pd.State;
                    node.MethodDetails.ExplicitDatas[i].DataValue = pd.Value;
                }
            }
            return this;
        }

        #endregion

        #region 节点方法的执行

        /// <summary>
        /// 开始执行
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task StartExecute(IDynamicContext context)
        {
            Stack<NodeModelBase> stack = new Stack<NodeModelBase>();
            stack.Push(this);
            var cts = context.Env.IOC.Get<CancellationTokenSource>(FlowStarter.FlipFlopCtsName);
            while (stack.Count > 0 ) // 循环中直到栈为空才会退出循环
            {
                if(cts is not null)
                {
                    if (cts.IsCancellationRequested)
                        break;
                }
                // 节点执行异常时跳过执行

                // 从栈中弹出一个节点作为当前节点进行处理
                var currentNode = stack.Pop();

                // 设置方法执行的对象
                if (currentNode.MethodDetails?.ActingInstance is not null && currentNode.MethodDetails?.ActingInstanceType is not null)
                {
                    currentNode.MethodDetails.ActingInstance = context.Env.IOC.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType);
                }

                #region 执行相关

                // 首先执行上游分支
                var upstreamNodes = currentNode.SuccessorNodes[ConnectionType.Upstream];
                for (int i = upstreamNodes.Count - 1; i >= 0; i--)
                {
                    // 筛选出启用的节点
                    if (upstreamNodes[i].DebugSetting.IsEnable)
                    {
                        if (upstreamNodes[i].DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
                        {
                            var cancelType = await upstreamNodes[i].DebugSetting.GetInterruptTask();
                            await Console.Out.WriteLineAsync($"[{upstreamNodes[i].MethodDetails.MethodName}]中断已{cancelType}，开始执行后继分支");
                        }
                        upstreamNodes[i].PreviousNode = currentNode;
                        await upstreamNodes[i].StartExecute(context); // 执行流程节点的上游分支
                    }
                }


                // 执行当前节点
                object? newFlowData = await currentNode.ExecutingAsync(context);
                if (cts is  null || cts.IsCancellationRequested || currentNode.NextOrientation == ConnectionType.None)
                {
                    // 不再执行
                    break;
                }
                await RefreshFlowDataAndExpInterrupt(context, currentNode, newFlowData); // 执行当前节点后刷新数据
                #endregion


                #region 执行完成

                // 选择后继分支
                var nextNodes = currentNode.SuccessorNodes[currentNode.NextOrientation];

                // 将下一个节点集合中的所有节点逆序推入栈中
                for (int i = nextNodes.Count - 1; i >= 0; i--)
                {
                    // 筛选出启用的节点、未被中断的节点
                    if (nextNodes[i].DebugSetting.IsEnable /*&& nextNodes[i].DebugSetting.InterruptClass == InterruptClass.None*/)
                    {
                        if (nextNodes[i].DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
                        {
                            var cancelType = await nextNodes[i].DebugSetting.GetInterruptTask();
                            await Console.Out.WriteLineAsync($"[{nextNodes[i].MethodDetails.MethodName}]中断已{cancelType}，开始执行后继分支");
                        }
                        nextNodes[i].PreviousNode = currentNode;
                        stack.Push(nextNodes[i]);
                    }
                }
                #endregion

            }
        }

        
        /// <summary>
        /// 执行节点对应的方法
        /// </summary>
        /// <param name="context">流程上下文</param>
        /// <returns>节点传回数据对象</returns>
        public virtual async Task<object?> ExecutingAsync(IDynamicContext context)
        {
            #region 调试中断

            if (DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
            {
                var cancelType = await this.DebugSetting.GetInterruptTask();
                //if(cancelType == CancelType.Discard)
                //{
                //    this.NextOrientation = ConnectionType.None;
                //    return null;
                //}
                await Console.Out.WriteLineAsync($"[{this.MethodDetails.MethodName}]中断已{cancelType}，开始执行后继分支");
            }

            #endregion

            MethodDetails md = MethodDetails;
            var del = md.MethodDelegate.Clone();
            object instance = md.ActingInstance;

            var haveParameter = md.ExplicitDatas.Length > 0;
            var haveResult = md.ReturnType != typeof(void);
            try
            {
                // Action/Func([方法作用的实例],[可能的参数值],[可能的返回值])
                object?[]? parameters = GetParameters(context, this, md);
                object? result = (haveParameter, haveResult) switch
                {
                    (false, false) => Execution((Action<object>)del, instance), // 调用节点方法，返回null
                    (true, false) => Execution((Action<object, object?[]?>)del, instance, parameters),  // 调用节点方法，返回null
                    (false, true) => Execution((Func<object, object?>)del, instance),  // 调用节点方法，返回方法传回类型
                    (true, true) => Execution((Func<object, object?[]?, object?>)del, instance, parameters), // 调用节点方法，获取入参参数，返回方法忏悔类型
                };

                NextOrientation = ConnectionType.IsSucceed;
                return result;
            }
            catch (Exception ex)
            {
                NextOrientation = ConnectionType.IsError;
                RuningException = ex;
                return null;
            }
        }


        #region 节点转换的委托类型
        public static object? Execution(Action<object> del, object instance)
        {
            del?.Invoke(instance);
            return null;
        }
        public static object? Execution(Action<object, object?[]?> del, object instance, object?[]? parameters)
        {
            del?.Invoke(instance, parameters);
            return null;
        }
        public static object? Execution(Func<object, object?> del, object instance)
        {
            return del?.Invoke(instance);
        }
        public static object? Execution(Func<object, object?[]?, object?> del, object instance, object?[]? parameters)
        {
            return del?.Invoke(instance, parameters);
        }
        #endregion


        /// <summary>
        /// 获取对应的参数数组
        /// </summary>
        public static object?[]? GetParameters(IDynamicContext context, NodeModelBase nodeModel, MethodDetails md)
        {
            // 用正确的大小初始化参数数组
            if (md.ExplicitDatas.Length == 0)
            {
                return null;// md.ActingInstance
            }

            object?[]? parameters = new object[md.ExplicitDatas.Length];
            var flowData = nodeModel.PreviousNode?.FlowData; // 当前传递的数据
            var previousDataType = flowData?.GetType();

            for (int i = 0; i < parameters.Length; i++)
            {

                object? inputParameter; // 存放解析的临时参数
                var ed = md.ExplicitDatas[i]; // 方法入参描述


                if (ed.IsExplicitData)
                {

                    if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
                    {
                        // 执行表达式从上一节点获取对象
                        inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, flowData, out _);
                    }
                    else
                    {
                        // 使用输入的固定值
                        inputParameter = ed.DataValue;
                    }
                }
                else
                {
                    inputParameter = flowData;   // 使用上一节点的对象
                }

                try
                {
                    parameters[i] = ed.DataType switch
                    {
                        //Type t when t == previousDataType => inputParameter, // 上下文
                        Type t when t == typeof(IDynamicContext) => context, // 上下文
                        Type t when t == typeof(MethodDetails) => md, // 节点方法描述
                        Type t when t == typeof(NodeModelBase) => nodeModel, // 节点实体类
                        Type t when t == typeof(Guid) => new Guid(inputParameter?.ToString()),
                        Type t when t == typeof(DateTime) => DateTime.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(string) => inputParameter?.ToString(),
                        Type t when t == typeof(char) => char.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(bool) => inputParameter is null ? false : bool.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(float) => inputParameter is null ? 0F : float.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(decimal) => inputParameter is null ? 0 : decimal.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(double) => inputParameter is null ? 0 : double.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(sbyte) => inputParameter is null ? 0 : sbyte.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(byte) => inputParameter is null ? 0 : byte.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(short) => inputParameter is null ? 0 : short.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(ushort) => inputParameter is null ? 0U : ushort.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(int) => inputParameter is null ? 0 : int.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(uint) => inputParameter is null ? 0U : uint.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(long) => inputParameter is null ? 0L : long.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(ulong) => inputParameter is null ? 0UL : ulong.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(nint) => inputParameter is null ? 0 : nint.Parse(inputParameter?.ToString()),
                        Type t when t == typeof(nuint) => inputParameter is null ? 0 : nuint.Parse(inputParameter?.ToString()),



                        Type t when t.IsEnum => Enum.Parse(ed.DataType, ed.DataValue),// 需要枚举
                        Type t when t.IsArray => (inputParameter as Array)?.Cast<object>().ToList(),
                        Type t when t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>) => inputParameter,
                        Type t when Nullable.GetUnderlyingType(t) != null => inputParameter is null ? null : Convert.ChangeType(inputParameter, Nullable.GetUnderlyingType(t)),
                        _ => inputParameter,
                    };
                }
                catch (Exception ex) // 节点参数类型转换异常
                {
                    parameters[i] = null;
                    Console.WriteLine(ex);
                }
            }
            return parameters;
        }

        /// <summary>
        /// 更新节点数据，并检查监视表达式是否生效
        /// </summary>
        /// <param name="newData"></param>
        public static async Task RefreshFlowDataAndExpInterrupt(IDynamicContext context,NodeModelBase nodeModel, object? newData = null)
        {

            string guid = nodeModel.Guid;
            if(newData is not null)
            {
                await MonitorObjExpInterrupt(context, nodeModel, newData, 0); // 首先监视对象
                await MonitorObjExpInterrupt(context, nodeModel, newData, 1); // 然后监视节点
                nodeModel.FlowData = newData; // 替换数据
            }



            //if(context.Env.CheckObjMonitorState(newData, out List<string> exps)) // 如果新的数据处于查看状态，通知UI进行更新？交给运行环境判断？
            //{
            //    context.Env.MonitorObjectNotification(guid, newData); // 对象处于监视状态，通知UI更新数据显示
            //    if (exps.Count > 0)
            //    {
            //        // 表达式环境下判断是否需要执行中断
            //        bool isExpInterrupt = false;
            //        string? exp = "";
            //        // 判断执行监视表达式，直到为 true 时退出
            //        for (int i = 0; i < exps.Count && !isExpInterrupt; i++)
            //        {
            //            exp = exps[i];
            //            isExpInterrupt = SereinConditionParser.To(newData, exp);
            //        }

            //        if (isExpInterrupt) // 触发中断
            //        {
            //            InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
            //            if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
            //            {
            //                context.Env.TriggerInterrupt(guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Obj);
            //                var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
            //                await Console.Out.WriteLineAsync($"[{newData}]中断已{cancelType}，开始执行后继分支");
            //            }
            //        }
            //    }

            //}


            //if (newData is not null && nodeModel.DebugSetting.InterruptExpressions.Count > 0)  // 检查节点是否存在监视表达式
            //{
            //    // 表达式环境下判断是否需要执行中断
            //    bool isExpInterrupt = false;
            //    string? exp = "";
            //    // 判断执行监视表达式，直到为 true 时退出
            //    for (int i = 0; i < nodeModel.DebugSetting.InterruptExpressions.Count && !isExpInterrupt; i++)
            //    {
            //        exp = nodeModel.DebugSetting.InterruptExpressions[i];
            //        isExpInterrupt = SereinConditionParser.To(newData, exp);
            //    }

            //    if (isExpInterrupt) // 触发中断
            //    {
            //        InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
            //        if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
            //        {
            //            context.Env.TriggerInterrupt(guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
            //            var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
            //            await Console.Out.WriteLineAsync($"[{nodeModel.MethodDetails.MethodName}]中断已{cancelType}，开始执行后继分支");
            //        }

            //    }
            //}



            //else if (nodeModel.DebugSetting.InterruptClass != InterruptClass.None)
            //{
            //    var cancelType = await nodeModel.DebugSetting.InterruptTask;
            //    await Console.Out.WriteLineAsync($"[{nodeModel.MethodDetails.MethodName}]中断已{(cancelType == CancelType.Manual ? "手动取消" : "自动取消")}，开始执行后继分支");
            //}



            //if (nodeModel.DebugSetting.IsMonitorFlowData)
            //{
            //    // 节点是否监视了数据，如果是，调用环境接口触发其相关事件。
            //    context.Env.FlowDataNotification(guid, newData);
            //}
        }

        private static async Task MonitorObjExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object data, int type)
        {
            MonitorObjectEventArgs.ObjSourceType sourceType;
            string key;
            if(type == 0)
            {
                key = data.GetType().FullName;
                sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
            }
            else
            {
                key = nodeModel.Guid;
                sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;

            }
            if (context.Env.CheckObjMonitorState(key, out List<string> exps)) // 如果新的数据处于查看状态，通知UI进行更新？交给运行环境判断？
            {
                context.Env.MonitorObjectNotification(nodeModel.Guid, data, sourceType); // 对象处于监视状态，通知UI更新数据显示
                if (exps.Count > 0)
                {
                    // 表达式环境下判断是否需要执行中断
                    bool isExpInterrupt = false;
                    string? exp = "";
                    // 判断执行监视表达式，直到为 true 时退出
                    for (int i = 0; i < exps.Count && !isExpInterrupt; i++)
                    {
                        exp = exps[i];
                        if (string.IsNullOrEmpty(exp)) continue;
                        isExpInterrupt = SereinConditionParser.To(data, exp);
                    }

                    if (isExpInterrupt) // 触发中断
                    {
                        InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
                        if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
                        {
                            context.Env.TriggerInterrupt(nodeModel.Guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
                            var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
                            await Console.Out.WriteLineAsync($"[{data}]中断已{cancelType}，开始执行后继分支");
                        }
                    }
                }

            }
        }
      

        /// <summary>
        /// 释放对象
        /// </summary>
        public void ReleaseFlowData()
        {
            if (typeof(IDisposable).IsAssignableFrom(FlowData?.GetType()) && FlowData is IDisposable disposable)
            {
                disposable?.Dispose();
            }
            this.FlowData = null;
        }

        /// <summary>
        /// 获取节点数据
        /// </summary>
        /// <returns></returns>
        public object? GetFlowData()
        {
            return this.FlowData;
        }
        #endregion

    }
}
