using MainShell.Common;
using MainShell.ProcessResult;
using MW.WorkFlow;
using Stylet;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace MainShell.Process
{
    public class WorkflowRunCompletedEventArgs : EventArgs
    {
        public WorkflowState FinalState { get; }
        public string Error { get; }
        public string FailureMessage { get; }
        public MessageKey FailureMessageKey { get; }
        public object[] FailureMessageArguments { get; }

        public WorkflowRunCompletedEventArgs(WorkflowState finalState, string error, string failureMessage, MessageKey failureMessageKey, object[] failureMessageArguments)
        {
            FinalState = finalState;
            Error = error;
            FailureMessage = failureMessage;
            FailureMessageKey = failureMessageKey;
            FailureMessageArguments = failureMessageArguments ?? Array.Empty<object>();
        }
    }

    /// <summary>
    /// 封装工作流的启动、停止和状态管理，用于手动流程的复用。
    /// </summary>
    public class 
        WorkflowRunner : PropertyChangedBase, IDisposable
    {
        private WorkflowEngine _workflowEngine;
        private bool _isRunning;

        /// <summary>
        /// 流程是否正在运行
        /// </summary>
        public bool IsRunning
        {
            get { return _isRunning; }
            private set { SetAndNotify(ref _isRunning, value); }
        }

        public event EventHandler<WorkflowRunCompletedEventArgs> RunCompleted;

        /// <summary>
        /// 运行单个 Activity（自动包装为单步工作流）
        /// </summary>
        public Task RunActivityAsync(IActivity activity, WorkflowContext context)
        {
            if (activity == null) throw new ArgumentNullException(nameof(activity));

            // 自动构建单步工作流定义
            var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
            var step = new WorkflowStep(stepId, activity);
            var definition = new WorkflowDefinition(stepId);
            definition.AddStep(step);

            return RunAsync(definition, context);
        }

        public Task<WorkflowRunCompletedEventArgs> RunActivityWithResultAsync(IActivity activity, WorkflowContext context)
        {
            if (activity == null) throw new ArgumentNullException(nameof(activity));

            var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
            var step = new WorkflowStep(stepId, activity);
            var definition = new WorkflowDefinition(stepId);
            definition.AddStep(step);

            return RunWithResultAsync(definition, context, null);
        }

        /// <summary>
        /// 运行完整的工作流定义
        /// </summary>
        public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context)
        {
            await RunWithResultAsync(definition, context, null);
        }

        public Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context)
        {
            return RunWithResultAsync(definition, context, null);
        }

        /// <summary>
        /// 运行完整的工作流定义，并支持从指定步骤启动。
        /// </summary>
        /// <param name="definition">工作流定义</param>
        /// <param name="context">工作流上下文</param>
        /// <param name="startStepId">可选：指定起始步骤ID；为 null/空时从初始步骤启动</param>
        public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
        {
            await RunWithResultAsync(definition, context, startStepId);
        }

        public async Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
        {
            if (definition == null) throw new ArgumentNullException(nameof(definition));
            if (context == null) throw new ArgumentNullException(nameof(context));

            if (IsRunning)
            {
                throw new InvalidOperationException("当前已有流程正在运行，无法重复启动。");
            }

            if (!string.IsNullOrWhiteSpace(startStepId) && !definition.GetAllStepIds().Contains(startStepId))
            {
                throw new ArgumentException($"指定的起始步骤ID '{startStepId}' 不存在于工作流定义中。", nameof(startStepId));
            }

            var resolvedStartStepId = ResolveStartStepId(definition, context, startStepId);

            var errorStr = string.Empty;
            WorkflowState finalState = WorkflowState.Created;
            MessageKey failureMessageKey = MessageKey.None;
            object[] failureMessageArguments = Array.Empty<object>();
            string failureMessage = string.Empty;

            try
            {
                IsRunning = true;
                _workflowEngine = new WorkflowEngine(definition, context);
                _workflowEngine.Start(resolvedStartStepId);

                // 异步轮询等待工作流结束
                // 这样可以不阻塞 UI 线程，同时保持 IsRunning 状态正确
                while (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
                {
                    await Task.Delay(100);
                }

                // 捕获最终状态（Dispose 之前）
                if (_workflowEngine != null)
                {
                    finalState = _workflowEngine.CurrentState;
                }

                failureMessageKey = ResolveFailureMessageKey(context);
                failureMessageArguments = ResolveFailureMessageArguments(context);
                failureMessage = ResolveFailureMessage(context, failureMessageKey, failureMessageArguments);
            }
            finally
            {
                // 无论正常结束、异常还是被取消，都确保清理资源和复位状态
                errorStr = _workflowEngine?.LastException?.ToString();
                IsRunning = false;
                _workflowEngine?.Dispose();
                _workflowEngine = null;
            }

            var completedArgs = new WorkflowRunCompletedEventArgs(finalState, errorStr, failureMessage, failureMessageKey, failureMessageArguments);
            RunCompleted?.Invoke(this, completedArgs);

            return completedArgs;
        }

        /// <summary>
        /// 从指定步骤启动工作流（语义化封装）。
        /// </summary>
        public Task RunFromStepAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
        {
            if (string.IsNullOrWhiteSpace(startStepId))
                throw new ArgumentNullException(nameof(startStepId));

            return RunAsync(definition, context, startStepId);
        }

        public Task<WorkflowRunCompletedEventArgs> RunFromStepWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
        {
            if (string.IsNullOrWhiteSpace(startStepId))
                throw new ArgumentNullException(nameof(startStepId));

            return RunWithResultAsync(definition, context, startStepId);
        }

        private string ResolveStartStepId(WorkflowDefinition definition, WorkflowContext context, string startStepId)
        {
            if (!string.IsNullOrWhiteSpace(startStepId))
            {
                return startStepId;
            }

            if (!context.TryGetData<string>(WorkflowContextKeys.WorkflowName, out var workflowName) ||
                string.IsNullOrWhiteSpace(workflowName) ||
                !context.TryGetData<ProcessResultManager>(WorkflowContextKeys.ProcessResultManager, out var resultManager) ||
                resultManager == null ||
                !resultManager.TryGetResumeStepId(workflowName, out var resumeStepId) ||
                !definition.ContainsStep(resumeStepId))
            {
                return null;
            }

            return resumeStepId;
        }

        private MessageKey ResolveFailureMessageKey(WorkflowContext context)
        {
            MessageKey failureMessageKey;
            if (context.TryGetData<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out failureMessageKey))
            {
                return failureMessageKey;
            }

            return MessageKey.None;
        }

        private object[] ResolveFailureMessageArguments(WorkflowContext context)
        {
            object[] failureMessageArguments;
            if (context.TryGetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, out failureMessageArguments) &&
                failureMessageArguments != null)
            {
                return failureMessageArguments;
            }

            return Array.Empty<object>();
        }

        private string ResolveFailureMessage(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
        {
            if (failureMessageKey != MessageKey.None)
            {
                return LanguageResourceHelper.Format(failureMessageKey, failureMessageArguments);
            }

            string failureMessage;
            if (context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out failureMessage) &&
                !string.IsNullOrWhiteSpace(failureMessage))
            {
                return failureMessage;
            }

            return string.Empty;
        }

        /// <summary>
        /// 请求停止当前流程
        /// </summary>
        public async Task StopAsync()
        {
            if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
            {
                await _workflowEngine.StopAsync();
            }
        }

        public void Pause()
        {
            if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
            {
                _workflowEngine.Pause();
            }
        }

        public void Resume()
        {
            if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
            {
                _workflowEngine.Resume();
            }
        }

        public void Dispose()
        {
            _workflowEngine?.Dispose();
        }
    }
}
