using BOB.Models;
using BOB.Singleton;
using Common.PubEvent;
using Common.Tools;
using Logger;
using MaterialDesignThemes.Wpf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static BOB.Models.ParameterModel;


namespace BOB
{
    public class StepRunning
    {
        private GlobalVariables _globalVariables;
        private Devices _devices;
        private IContainerProvider containerProvider;
        private IEventAggregator _eventAggregator;
        
        private  readonly Dictionary<Guid, ParameterModel> tmpParameters = [];

        private  readonly Stopwatch stepStopwatch = new();

        private  readonly Stack<Stopwatch> loopStopwatchStack = new();

        private  readonly Stack<LoopContext> loopStack = new();

        public  CancellationTokenSource stepCTS = new();
        private  bool SubSingleStep = false;

        private  Guid TestRoundID;
        public StepRunning(GlobalVariables globalVariables,IEventAggregator eventAggregator,IContainerProvider containerProvider)
        {
            _globalVariables = containerProvider.Resolve<GlobalVariables>(); 
            _eventAggregator = eventAggregator;
            _devices = containerProvider.Resolve<Devices>();
        }
        public  async Task<bool> ExecuteSteps(ProgramModel program, int depth = 0, CancellationToken cancellationToken = default)
        {
            int index = 0;
            bool stepSuccess = false;
            if (depth == 0)
            {
                loopStack.Clear();
                loopStopwatchStack.Clear();
                ResetAllStepStatus(program);
                tmpParameters.Clear();
                TestRoundID = Guid.NewGuid();
            }
            foreach (var item in program.Parameters)
            {
                tmpParameters.TryAdd(item.ID, item);
            }

            while (index < program.StepCollection.Count)
            {
                while (_globalVariables.IsStop == true)
                {
                    await Task.Delay(50);
                }
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }
                var step = program.StepCollection[index];
                if (!step.IsUsed)
                {
                    index++;
                    continue;
                }

                step.Result = 0;
                if (step.StepType == "循环开始")
                {
                    var endStep = program.StepCollection.FirstOrDefault(x => x.LoopStartStepId == step.ID);
                    if (endStep != null)
                    {
                        endStep.Result = 0;
                    }
                    else
                    {
                        LoggerHelper.ErrorWithNotify("程序循环指令未闭合，请检查后重试");
                        break;
                    }
                }

                // 处理循环开始
                if (step.StepType == "循环开始")
                {
                    Stopwatch loopStopwatch = new();
                    loopStopwatch.Start();
                    loopStopwatchStack.Push(loopStopwatch);
                    var context = new LoopContext
                    {
                        LoopCount = step.LoopCount ?? 1,
                        CurrentLoop = 0,
                        StartIndex = index,
                        LoopStartStep = step
                    };
                    loopStack.Push(context);
                    step.CurrentLoopCount = context.LoopCount;
                     LoggerHelper.InfoWithNotify($"循环开始，共{context.LoopCount}次", depth);
                    index++;
                }

                // 处理循环结束
                else if (step.StepType == "循环结束")
                {
                    if (loopStack.Count == 0)
                    {
                        LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth:depth);
                        step.Result = 2;
                        index++;
                        continue;
                    }

                    var context = loopStack.Peek();
                    context.CurrentLoop++;

                    // 更新循环开始步骤的显示
                    context.LoopStartStep!.CurrentLoopCount = context.LoopCount - context.CurrentLoop;

                    if (context.CurrentLoop < context.LoopCount)
                    {
                        // 继续循环：跳转到循环开始后的第一条指令
                        index = context.StartIndex + 1;
                        LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束，跳回开始，剩余{context.LoopCount - context.CurrentLoop}次", depth);
                    }
                    else
                    {
                        // 循环结束
                        loopStack.Pop();
                        var loopStopwatch = loopStopwatchStack.Peek();
                        index++;
                         LoggerHelper.InfoWithNotify($"循环结束，共执行{context.LoopCount}次", depth);
                        if (depth == 0 && loopStopwatch.IsRunning)
                        {
                            loopStopwatch.Stop();
                            step.RunTime = (int)loopStopwatch.ElapsedMilliseconds;
                            step.Result = 1;
                            program.StepCollection.First(x => x.ID == step.LoopStartStepId).Result = 1;
                            loopStopwatchStack.Pop();
                        }
                    }
                }

                // 处理普通步骤
                else
                {
                    if (depth == 0)
                    {
                        stepStopwatch.Restart();
                    }

                    if (step.SubProgram != null)
                    {
                        if (_globalVariables.SingleStep)//子程序的单步执行将执行完保存下的所有Method
                        {
                            SubSingleStep = true;
                            _globalVariables.SingleStep = false;
                        }
                         LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ]  [ {step.Name} ] ", depth);
                        stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
                        UpdateCurrentStepResult(step, true, stepSuccess, depth);
                        if (SubSingleStep)
                        {
                            SubSingleStep = false;
                            _globalVariables.SingleStep = true;
                        }
                    }
                    else if (step.Method != null)
                    {
                         LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ]  [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
                        await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken);
                        stepSuccess = step.Result == 1;
                        if (step.NGGotoStepID != null && !stepSuccess)
                        {
                            var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.NGGotoStepID);
                            if (tmp != null)
                            {
                                index = tmp.Index - 2;
                                 LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
                            }
                        }
                        if (step.OKGotoStepID != null && stepSuccess)
                        {
                            var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.OKGotoStepID);
                            if (tmp != null)
                            {
                                index = tmp.Index - 2;
                                 LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
                            }
                        }
                    }
                    index++;

                    if (depth == 0 && stepStopwatch.IsRunning)
                    {
                        stepStopwatch.Stop();
                        step.RunTime = (int)stepStopwatch.ElapsedMilliseconds;
                    }
                    if (_globalVariables.SingleStep)
                    {
                        _globalVariables.IsStop = true;
                        _globalVariables.RunState = "运行";
                        _globalVariables.SingleStep = false;
                        _eventAggregator.GetEvent<UpdateIconEvent>().Publish("Play");
                    }
                }
            }

            return loopStack.Count == 0 && stepSuccess;
        }

        public  async Task ExecuteMethodStep(StepModel step, Dictionary<Guid, ParameterModel> parameters, int depth, CancellationToken cancellationToken = default)
        {
            try
            {
                if(_globalVariables.Program.StepCollection.Count>1)
                _globalVariables.SelectedStep = null;
                await Task.Delay(SystemConfig.Instance.PerformanceLevel);

                // 1. 查找类型
                Type? targetType = null;
                foreach (var assembly in _globalVariables.Assemblies)
                {
                    targetType = assembly.GetType(step.Method!.FullName!);
                    if (targetType != null) break;
                }
                if (targetType == null)
                {
                    LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误：未找到类型 {step.Method!.FullName}", depth: depth);
                    step.Result = 2;
                }

                // 2. 创建实例（仅当方法不是静态时才需要）
                object? instance = null;
                bool isMethod = false;

                // 3. 准备参数
                var inputParams = new List<object?>();
                var paramTypes = new List<Type>();
                ParameterModel? outputParam = null;
                foreach (var param in step.Method!.Parameters)
                {
                    if (param.Category == ParameterCategory.Input)
                    {
                        if (param.Type == typeof(CancellationToken))
                        {
                            inputParams.Add(stepCTS.Token);
                            paramTypes.Add(param.Type!);
                            continue;
                        }
                        var actualValue = param.GetActualValue(tmpParameters);
                        // 类型转换处理
                        if (actualValue != null)
                        {
                            if (string.IsNullOrEmpty(actualValue.ToString()))
                            {
                                actualValue = null;
                            }
                            if (actualValue != null && param.Type != null && actualValue.GetType() != param.Type)
                            {
                                try
                                {
                                    if (param.Type.IsArray)
                                    {
                                        // 获取数组元素类型
                                        Type elementType = param.Type.GetElementType()!;

                                        // 解析字符串为字符串数组
                                        string[] stringArray = actualValue.ToString()!
                                            .Trim('[', ']')
                                            .Split(',', StringSplitOptions.RemoveEmptyEntries)
                                            .Select(s => s.Trim())
                                            .ToArray();

                                        // 创建目标类型数组
                                        Array array = Array.CreateInstance(elementType, stringArray.Length);

                                        // 转换每个元素
                                        for (int i = 0; i < stringArray.Length; i++)
                                        {
                                            try
                                            {
                                                // 特殊处理字符串类型
                                                if (elementType == typeof(string))
                                                {
                                                    array.SetValue(stringArray[i], i);
                                                }
                                                // 特殊处理枚举类型
                                                else if (elementType.IsEnum)
                                                {
                                                    array.SetValue(Enum.Parse(elementType, stringArray[i]), i);
                                                }
                                                // 常规类型转换
                                                else
                                                {
                                                    array.SetValue(Convert.ChangeType(stringArray[i], elementType), i);
                                                }
                                            }
                                            catch
                                            {
                                                throw new InvalidCastException($"指令 [ {step.Index} ] 执行错误：元素 '{stringArray[i]}' 无法转换为 {elementType.Name}[]");
                                            }
                                        }
                                        actualValue = array;
                                    }
                                    else
                                    {
                                        if (param.Type.BaseType == typeof(Enum))
                                        {
                                            actualValue = Enum.Parse(param.Type, param.Value!.ToString()!);
                                        }
                                        else
                                        {
                                            actualValue = Convert.ChangeType(actualValue, param.Type);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误：参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth);
                                }
                            }
                        }
                        inputParams.Add(actualValue);
                        paramTypes.Add(param.Type!);
                    }
                    else if (param.Category == ParameterCategory.Output)
                    {
                        outputParam = param;
                    }
                }

                // 4. 获取方法
                var method = targetType!.GetMethod(
                    step.Method.Name!,
                     BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance,
                    null,
                    paramTypes.ToArray(),
                    null
                );

                if (method == null)
                {
                    LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误：未找到方法{step.Method.Name}", depth: depth);
                    step.Result = 2;
                }

                // 检查是否是静态方法
                 bool isStaticMethod = method!.IsStatic;

                // 如果是实例方法，需要创建实例
                if (!isStaticMethod)
                {
                    try
                    {
                        instance = _devices.DeviceDic[targetType.Name];
                    }
                    catch (Exception ex)
                    {
                        LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误：创建实例失败 - {ex.Message}", depth: depth);
                        step.Result = 2;
                    }
                }

                // 5. 执行方法

                object? returnValue = method.Invoke(instance, inputParams.ToArray());
                try
                {
                    // 处理异步方法
                    if (returnValue is Task task)
                    {
                        await task.ConfigureAwait(false);
                        // 获取结果（如果是Task<T>）
                        if (task.GetType().IsGenericType)
                        {
                            var returnValueProperty = task.GetType().GetProperty("Result");
                            returnValue = returnValueProperty?.GetValue(task);
                        }
                        else
                        {
                            returnValue = null;
                        }
                    }

                    // 处理VoidTaskreturnValue类型
                    if (returnValue != null && returnValue.GetType().FullName == "System.Threading.Tasks.VoidTaskreturnValue")
                    {
                        returnValue = null;
                    }
                }
                catch (OperationCanceledException)
                {
                    return;
                }
                catch (Exception ex)
                {
                    LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
                    step.Result = 2;
                    return;
                }

                // 6. 处理输出
                bool paraResult = true; //记录参数上下限是否NG
                if (outputParam != null)
                {
                    outputParam.Value = returnValue;
                    var currentPara = outputParam.GetCurrentParameter(tmpParameters);
                    if (currentPara != null)
                    {
                        currentPara.Value = returnValue;
                        var tmp = currentPara.GetResult();
                        currentPara.Result = tmp.Item1;
                        paraResult = tmp.Item1;
                        if (tmp.Item2 != null)
                        {
                            LoggerHelper.WarnWithNotify(tmp.Item2);
                        }
                        if (currentPara.IsSave && _globalVariables.Program.Parameters.FirstOrDefault(x => x.ID == currentPara.ID) != null)
                        {
                            _ = SaveDataToDatabase(_globalVariables.Program.ID, currentPara);
                        }
                    }
                    var returnType = returnValue?.GetType();
                    if (returnType != null)
                    {
                        if (!returnType.IsArray)
                        {
                            LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = {returnValue} ({returnType.Name})", depth);
                        }
                        else
                        {
                            if (returnValue is IEnumerable enumerable)
                            {
                                var elements = enumerable.Cast<object>().Select(item => item?.ToString() ?? "null");
                                LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = [ {string.Join(", ", elements)} ] ({returnType.Name})", depth);
                            }
                        }
                    }
                }
                LoggerHelper.SuccessWithNotify($"指令 [ {step.Index} ] 执行成功", depth);
                UpdateCurrentStepResult(step, paraResult: paraResult, depth: depth);
            }
            catch (OperationCanceledException)
            {
                return;
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
                step.Result = 2;
                return;
            }
        }

        public  void ResetAllStepStatus(ProgramModel program)
        {
            foreach (var step in program.StepCollection)
            {
                step.Result = -1;
                step.RunTime = null;
            }
        }

        private  void UpdateCurrentStepResult(StepModel step, bool paraResult = true, bool stepResult = true, int depth = 0)
        {
            if (stepResult && paraResult)
            {
                if (string.IsNullOrEmpty(step.OKExpression))
                {
                    step.Result = 1;
                }
                else
                {
                    Dictionary<string, object> paraDic = [];
                    foreach (var item in tmpParameters)
                    {
                        paraDic.TryAdd(item.Value.Name, item.Value.Value!);
                    }
                    if (step.SubProgram != null)
                    {
                        foreach (var item in step.SubProgram.Parameters.Where(x => x.Category == ParameterCategory.Output))
                        {
                            paraDic.TryAdd(item.Name, item.Value!);
                        }
                    }
                    else if (step.Method != null)
                    {
                        foreach (var item in step.Method.Parameters.Where(x => x.Category == ParameterCategory.Output))
                        {
                            paraDic.TryAdd(item.Name, item.Value!);
                        }
                    }
                    bool re = ExpressionEvaluator.EvaluateExpression(step.OKExpression, paraDic);
                    step.Result = re ? 1 : 2;
                    if (step.Result == 2)
                    {
                        LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth);
                    }
                }
            }
            else
            {
                if (!paraResult)
                {
                    LoggerHelper.WarnWithNotify("参数限值校验失败", depth: depth);
                }
                step.Result = 2;
            }
        }

        private  async Task SaveDataToDatabase(Guid programID, ParameterModel currentPara)
        {
            
        }

        #region 私有类

        private class LoopContext
        {
            public int LoopCount { get; set; }
            public int CurrentLoop { get; set; }
            public int StartIndex { get; set; }
            public StepModel? LoopStartStep { get; set; }
        }

        #endregion

    }
}
