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

namespace MainShell.Process
{
    public enum ChipPreparationAction
    {
        None = 0,
        Load = 1,
        Unload = 2,
        Completed = 3,
        Prepare = 4
    }

    public enum ChipPreparationStatus
    {
        Idle = 0,
        Preparing = 1,
        Prepared = 2,
        Paused = 3,
        Faulted = 4,
        Loading = 5,
        Loaded = 6,
        Unloading = 7
    }

    public class ChipPreparationRequest
    {
        public string RequestId { get; set; }

        public string RecipeName { get; set; }

        public ChipPreparationAction Action { get; set; } = ChipPreparationAction.Prepare;

        public string SourceStepId { get; set; }
    }

    public class ChipPreparationWaitResult
    {
        public bool Success { get; set; }

        public bool IsTimeout { get; set; }

        public bool IsCanceled { get; set; }

        public string ErrorMessage { get; set; }

        public static ChipPreparationWaitResult CreateSuccess()
        {
            return new ChipPreparationWaitResult
            {
                Success = true
            };
        }

        public static ChipPreparationWaitResult CreateTimeout(string errorMessage)
        {
            return new ChipPreparationWaitResult
            {
                IsTimeout = true,
                ErrorMessage = errorMessage
            };
        }

        public static ChipPreparationWaitResult CreateCanceled(string errorMessage)
        {
            return new ChipPreparationWaitResult
            {
                IsCanceled = true,
                ErrorMessage = errorMessage
            };
        }

        public static ChipPreparationWaitResult CreateFailure(string errorMessage)
        {
            return new ChipPreparationWaitResult
            {
                ErrorMessage = errorMessage
            };
        }
    }

    public class ChipPreparationStateSnapshot
    {
        public ChipPreparationStatus Status { get; set; }

        public string ActiveRequestId { get; set; }

        public string RecipeName { get; set; }

        public string SourceStepId { get; set; }

        public string CurrentStage { get; set; }

        public string ErrorMessage { get; set; }

        public DateTime LastUpdatedTime { get; set; }

        public ChipPreparationAction CurrentAction { get; set; }

        public bool IsChipLoaded { get; set; }
    }

    public class ChipPreparationState : PropertyChangedBase
    {
        private ChipPreparationStatus _status;
        private string _activeRequestId;
        private string _recipeName;
        private string _sourceStepId;
        private string _currentStage;
        private string _errorMessage;
        private DateTime _lastUpdatedTime;
        private ChipPreparationAction _currentAction;
        private bool _isChipLoaded;

        public ChipPreparationStatus Status
        {
            get { return _status; }
            set { SetAndNotify(ref _status, value); }
        }

        public string ActiveRequestId
        {
            get { return _activeRequestId; }
            set { SetAndNotify(ref _activeRequestId, value); }
        }

        public string RecipeName
        {
            get { return _recipeName; }
            set { SetAndNotify(ref _recipeName, value); }
        }

        public string SourceStepId
        {
            get { return _sourceStepId; }
            set { SetAndNotify(ref _sourceStepId, value); }
        }

        public string CurrentStage
        {
            get { return _currentStage; }
            set { SetAndNotify(ref _currentStage, value); }
        }

        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { SetAndNotify(ref _errorMessage, value); }
        }

        public DateTime LastUpdatedTime
        {
            get { return _lastUpdatedTime; }
            set { SetAndNotify(ref _lastUpdatedTime, value); }
        }

        public ChipPreparationAction CurrentAction
        {
            get { return _currentAction; }
            set { SetAndNotify(ref _currentAction, value); }
        }

        public bool IsChipLoaded
        {
            get { return _isChipLoaded; }
            set { SetAndNotify(ref _isChipLoaded, value); }
        }

        public bool IsBusy
        {
            get
            {
                return Status == ChipPreparationStatus.Preparing ||
                       Status == ChipPreparationStatus.Loading ||
                       Status == ChipPreparationStatus.Unloading;
            }
        }

        public bool IsReady
        {
            get
            {
                return Status == ChipPreparationStatus.Prepared ||
                       Status == ChipPreparationStatus.Loaded ||
                       (Status == ChipPreparationStatus.Idle && CurrentAction == ChipPreparationAction.Unload);
            }
        }

        public bool IsFaulted
        {
            get { return Status == ChipPreparationStatus.Faulted; }
        }

        public void ApplySnapshot(ChipPreparationStateSnapshot snapshot)
        {
            if (snapshot == null)
            {
                return;
            }

            Status = snapshot.Status;
            ActiveRequestId = snapshot.ActiveRequestId;
            RecipeName = snapshot.RecipeName;
            SourceStepId = snapshot.SourceStepId;
            CurrentStage = snapshot.CurrentStage;
            ErrorMessage = snapshot.ErrorMessage;
            LastUpdatedTime = snapshot.LastUpdatedTime;
            CurrentAction = snapshot.CurrentAction;
            IsChipLoaded = snapshot.IsChipLoaded;
            NotifyOfPropertyChange(nameof(IsBusy));
            NotifyOfPropertyChange(nameof(IsReady));
            NotifyOfPropertyChange(nameof(IsFaulted));
        }
    }

    public class ChipPreparationRequestedEventArgs : EventArgs
    {
        public ChipPreparationRequestedEventArgs(ChipPreparationRequest request)
        {
            Request = request;
        }

        public ChipPreparationRequest Request { get; private set; }
    }

    public class ChipPreparationStateChangedEventArgs : EventArgs
    {
        public ChipPreparationStateChangedEventArgs(ChipPreparationStateSnapshot snapshot)
        {
            Snapshot = snapshot;
        }

        public ChipPreparationStateSnapshot Snapshot { get; private set; }
    }

    public interface IChipPreparationService
    {
        ChipPreparationState Current { get; }

        bool TryRequestPrepare(ChipPreparationRequest request, out string rejectReason);

        Task<ChipPreparationWaitResult> WaitUntilReadyAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));

        Task<ChipPreparationWaitResult> WaitUntilLoadedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));

        Task<ChipPreparationWaitResult> EnsurePreparedAsync(ChipPreparationRequest request, TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));

        bool TryMarkReady(string requestId, out string rejectReason);

        bool TryMarkFault(string errorMessage, out string rejectReason);

        bool TryConsumeReady(out string rejectReason);

        Task CancelAsync(CancellationToken cancellationToken = default(CancellationToken));

        void Pause();

        void Resume();

        bool TryResetFault(out string failureReason);
    }

    public class ChipPreparationService : IChipPreparationService
    {
        private readonly object _syncRoot = new object();
        private readonly IEventAggregator _eventAggregator;
        private readonly ProcessResultManager _processResultManager;
        private ChipPreparationRequest _activeRequest;
        private ChipPreparationRequest _pendingLoadRequest;
        private ChipPreparationStateSnapshot _snapshot;

        public ChipPreparationService(IEventAggregator eventAggregator, ProcessResultManager processResultManager)
        {
            _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
            _processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
            _processResultManager.ReloadAll();
            _snapshot = RestoreSnapshot(_processResultManager.PreparationAreaState);
            Current = new ChipPreparationState();
            Current.ApplySnapshot(_snapshot);
        }

        public ChipPreparationState Current { get; private set; }

        public bool TryRequestPrepare(ChipPreparationRequest request, out string rejectReason)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (!TryValidateActionRequest(request, out rejectReason))
            {
                return false;
            }

            if (string.IsNullOrWhiteSpace(request.RequestId))
            {
                request.RequestId = Guid.NewGuid().ToString("N");
            }

            ChipPreparationRequest requestToPublish = null;
            ChipPreparationStateSnapshot snapshotToPublish = null;

            lock (_syncRoot)
            {
                if (_snapshot.Status == ChipPreparationStatus.Faulted)
                {
                    rejectReason = string.IsNullOrWhiteSpace(_snapshot.ErrorMessage) ? "芯片准备区当前处于故障状态。" : _snapshot.ErrorMessage;
                    return false;
                }

                if (_snapshot.Status == ChipPreparationStatus.Paused)
                {
                    rejectReason = "芯片准备区当前处于暂停状态。";
                    return false;
                }

                if (request.Action == ChipPreparationAction.Prepare)
                {
                    if (_snapshot.Status == ChipPreparationStatus.Preparing ||
                        _snapshot.Status == ChipPreparationStatus.Prepared ||
                        _snapshot.Status == ChipPreparationStatus.Loading ||
                        _snapshot.Status == ChipPreparationStatus.Loaded)
                    {
                        rejectReason = string.Empty;
                        return true;
                    }

                    if (_snapshot.Status == ChipPreparationStatus.Unloading)
                    {
                        rejectReason = "芯片准备区正在执行下料，不能发起准备。";
                        return false;
                    }

                    _activeRequest = CloneRequest(request);
                    _pendingLoadRequest = null;
                    _snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Preparing, _snapshot.IsChipLoaded);
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    requestToPublish = CloneRequest(_activeRequest);
                }
                else if (request.Action == ChipPreparationAction.Load)
                {
                    if (_snapshot.Status == ChipPreparationStatus.Loaded)
                    {
                        rejectReason = string.Empty;
                        return true;
                    }

                    if (_snapshot.Status == ChipPreparationStatus.Loading)
                    {
                        rejectReason = string.Empty;
                        return true;
                    }

                    if (_snapshot.Status == ChipPreparationStatus.Preparing)
                    {
                        _pendingLoadRequest = CloneRequest(request);
                        rejectReason = string.Empty;
                        return true;
                    }

                    if (_snapshot.Status == ChipPreparationStatus.Unloading)
                    {
                        rejectReason = "芯片准备区正在执行下料，不能发起上料。";
                        return false;
                    }

                    _activeRequest = CloneRequest(request);
                    _snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Loading, _snapshot.IsChipLoaded);
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    requestToPublish = CloneRequest(_activeRequest);
                }
                else
                {
                    if (_snapshot.Status == ChipPreparationStatus.Unloading)
                    {
                        rejectReason = string.Empty;
                        return true;
                    }

                    if (!_snapshot.IsChipLoaded && _snapshot.Status != ChipPreparationStatus.Loaded && _snapshot.Status != ChipPreparationStatus.Prepared)
                    {
                        rejectReason = "当前没有可执行下料的芯片。";
                        return false;
                    }

                    if (_snapshot.Status == ChipPreparationStatus.Preparing || _snapshot.Status == ChipPreparationStatus.Loading)
                    {
                        rejectReason = "芯片准备区正在执行准备或上料，不能发起下料。";
                        return false;
                    }

                    _activeRequest = CloneRequest(request);
                    _pendingLoadRequest = null;
                    _snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Unloading, true);
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    requestToPublish = CloneRequest(_activeRequest);
                }

                rejectReason = string.Empty;
            }

            PublishState(snapshotToPublish);
            if (requestToPublish != null)
            {
                _eventAggregator.Publish(new ChipPreparationRequestedEventArgs(requestToPublish));
            }

            return true;
        }

        public async Task<ChipPreparationWaitResult> WaitUntilReadyAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return await WaitForStateAsync(false, timeout, cancellationToken).ConfigureAwait(false);
        }

        public async Task<ChipPreparationWaitResult> WaitUntilLoadedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            return await WaitForStateAsync(true, timeout, cancellationToken).ConfigureAwait(false);
        }

        public async Task<ChipPreparationWaitResult> EnsurePreparedAsync(ChipPreparationRequest request, TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
        {
            string rejectReason;
            if (!TryRequestPrepare(request, out rejectReason))
            {
                return ChipPreparationWaitResult.CreateFailure(rejectReason);
            }

            return await WaitUntilReadyAsync(timeout, cancellationToken).ConfigureAwait(false);
        }

        public bool TryMarkReady(string requestId, out string rejectReason)
        {
            ChipPreparationStateSnapshot snapshotToPublish = null;
            ChipPreparationRequest requestToPublish = null;

            lock (_syncRoot)
            {
                if (_activeRequest == null)
                {
                    rejectReason = "当前没有正在执行的芯片准备请求。";
                    return false;
                }

                if (!string.IsNullOrWhiteSpace(requestId) &&
                    !string.Equals(_activeRequest.RequestId, requestId, StringComparison.OrdinalIgnoreCase))
                {
                    rejectReason = "芯片准备请求标识不匹配。";
                    return false;
                }

                if (_activeRequest.Action == ChipPreparationAction.Prepare)
                {
                    if (_pendingLoadRequest != null)
                    {
                        _activeRequest = CloneRequest(_pendingLoadRequest);
                        _pendingLoadRequest = null;
                        _snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Loading, true);
                        snapshotToPublish = CloneSnapshot(_snapshot);
                        requestToPublish = CloneRequest(_activeRequest);
                    }
                    else
                    {
                        _snapshot = CreateStableSnapshot(ChipPreparationStatus.Prepared, _activeRequest, true, "Prepared");
                        snapshotToPublish = CloneSnapshot(_snapshot);
                        _activeRequest = null;
                    }
                }
                else if (_activeRequest.Action == ChipPreparationAction.Load)
                {
                    _snapshot = CreateStableSnapshot(ChipPreparationStatus.Loaded, _activeRequest, true, "LoadedPendingTransfer");
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    _activeRequest = null;
                }
                else if (_activeRequest.Action == ChipPreparationAction.Unload)
                {
                    _snapshot = CreateIdleSnapshot(false);
                    _snapshot.CurrentAction = ChipPreparationAction.Unload;
                    _snapshot.CurrentStage = "UnloadCompleted";
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    _activeRequest = null;
                }
                else
                {
                    rejectReason = "芯片准备请求动作无效。";
                    return false;
                }

                rejectReason = string.Empty;
            }

            PublishState(snapshotToPublish);
            if (requestToPublish != null)
            {
                _eventAggregator.Publish(new ChipPreparationRequestedEventArgs(requestToPublish));
            }

            return true;
        }

        public bool TryMarkFault(string errorMessage, out string rejectReason)
        {
            ChipPreparationStateSnapshot snapshotToPublish;

            lock (_syncRoot)
            {
                if (_snapshot.Status == ChipPreparationStatus.Idle)
                {
                    rejectReason = "当前没有执行中的芯片流程。";
                    return false;
                }

                _snapshot = CreateFaultedSnapshot(_activeRequest, errorMessage, _snapshot.IsChipLoaded);
                _activeRequest = null;
                _pendingLoadRequest = null;
                snapshotToPublish = CloneSnapshot(_snapshot);
                rejectReason = string.Empty;
            }

            PublishState(snapshotToPublish);
            return true;
        }

        public bool TryConsumeReady(out string rejectReason)
        {
            ChipPreparationStateSnapshot snapshotToPublish;

            lock (_syncRoot)
            {
                if (_snapshot.Status == ChipPreparationStatus.Loaded || _snapshot.Status == ChipPreparationStatus.Prepared)
                {
                    ResetToIdle(false);
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    rejectReason = string.Empty;
                }
                else if (_snapshot.Status == ChipPreparationStatus.Idle && _snapshot.CurrentAction == ChipPreparationAction.Unload)
                {
                    _snapshot = CreateIdleSnapshot(false);
                    snapshotToPublish = CloneSnapshot(_snapshot);
                    rejectReason = string.Empty;
                }
                else
                {
                    rejectReason = "当前没有可消费的准备结果。";
                    return false;
                }
            }

            PublishState(snapshotToPublish);
            return true;
        }

        public Task CancelAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            ChipPreparationStateSnapshot snapshotToPublish = null;
            lock (_syncRoot)
            {
                if (!IsTransientStatus(_snapshot.Status))
                {
                    return Task.CompletedTask;
                }

                bool keepLoadedChip = _snapshot.IsChipLoaded && _snapshot.Status != ChipPreparationStatus.Unloading;
                _activeRequest = null;
                _pendingLoadRequest = null;
                _snapshot = CreateIdleSnapshot(keepLoadedChip);
                snapshotToPublish = CloneSnapshot(_snapshot);
            }

            PublishState(snapshotToPublish);
            return Task.CompletedTask;
        }

        public void Pause()
        {
            ChipPreparationStateSnapshot snapshotToPublish = null;
            lock (_syncRoot)
            {
                if (!IsTransientStatus(_snapshot.Status))
                {
                    return;
                }

                _snapshot = CloneSnapshot(_snapshot);
                _snapshot.Status = ChipPreparationStatus.Paused;
                _snapshot.CurrentStage = "Paused";
                _snapshot.LastUpdatedTime = DateTime.Now;
                snapshotToPublish = CloneSnapshot(_snapshot);
            }

            PublishState(snapshotToPublish);
        }

        public void Resume()
        {
            ChipPreparationStateSnapshot snapshotToPublish = null;
            lock (_syncRoot)
            {
                if (_snapshot.Status != ChipPreparationStatus.Paused || _activeRequest == null)
                {
                    return;
                }

                ChipPreparationStatus resumedStatus = ResolveRunningStatus(_activeRequest.Action);
                _snapshot = CloneSnapshot(_snapshot);
                _snapshot.Status = resumedStatus;
                _snapshot.CurrentStage = ResolveStageForStatus(resumedStatus);
                _snapshot.LastUpdatedTime = DateTime.Now;
                snapshotToPublish = CloneSnapshot(_snapshot);
            }

            PublishState(snapshotToPublish);
        }

        public bool TryResetFault(out string failureReason)
        {
            ChipPreparationStateSnapshot snapshotToPublish;

            lock (_syncRoot)
            {
                if (_snapshot.Status != ChipPreparationStatus.Faulted)
                {
                    failureReason = "当前芯片准备区未处于故障状态。";
                    return false;
                }

                ResetToIdle(_snapshot.IsChipLoaded);
                snapshotToPublish = CloneSnapshot(_snapshot);
                failureReason = string.Empty;
            }

            PublishState(snapshotToPublish);
            return true;
        }

        private async Task<ChipPreparationWaitResult> WaitForStateAsync(bool requireLoaded, TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (timeout <= TimeSpan.Zero)
            {
                timeout = TimeSpan.FromMilliseconds(100);
            }

            DateTime deadline = DateTime.Now.Add(timeout);
            try
            {
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    ChipPreparationWaitResult immediateResult = EvaluateWaitResult(requireLoaded);
                    if (immediateResult != null)
                    {
                        return immediateResult;
                    }

                    if (DateTime.Now >= deadline)
                    {
                        return ChipPreparationWaitResult.CreateTimeout(requireLoaded
                            ? "等待芯片上料完成超时。"
                            : "等待芯片准备完成超时。");
                    }

                    await Task.Delay(50, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (OperationCanceledException)
            {
                return ChipPreparationWaitResult.CreateCanceled(requireLoaded
                    ? "等待芯片上料已取消。"
                    : "等待芯片准备已取消。");
            }
        }

        private ChipPreparationWaitResult EvaluateWaitResult(bool requireLoaded)
        {
            lock (_syncRoot)
            {
                if (_snapshot.Status == ChipPreparationStatus.Faulted)
                {
                    return ChipPreparationWaitResult.CreateFailure(string.IsNullOrWhiteSpace(_snapshot.ErrorMessage)
                        ? "芯片准备区执行失败。"
                        : _snapshot.ErrorMessage);
                }

                if (requireLoaded)
                {
                    if (_snapshot.Status == ChipPreparationStatus.Loaded)
                    {
                        return ChipPreparationWaitResult.CreateSuccess();
                    }
                }
                else
                {
                    if (_snapshot.Status == ChipPreparationStatus.Prepared ||
                        _snapshot.Status == ChipPreparationStatus.Loaded ||
                        (_snapshot.Status == ChipPreparationStatus.Idle && _snapshot.CurrentAction == ChipPreparationAction.Unload))
                    {
                        return ChipPreparationWaitResult.CreateSuccess();
                    }
                }

                if (_snapshot.Status == ChipPreparationStatus.Idle && _activeRequest == null)
                {
                    return ChipPreparationWaitResult.CreateFailure("尚未开始芯片准备流程。") ;
                }

                return null;
            }
        }

        private void ResetToIdle(bool keepLoadedChip)
        {
            _activeRequest = null;
            _pendingLoadRequest = null;
            _snapshot = CreateIdleSnapshot(keepLoadedChip);
        }

        private void PublishState(ChipPreparationStateSnapshot snapshot)
        {
            if (snapshot == null)
            {
                return;
            }

            Current.ApplySnapshot(snapshot);
            _processResultManager.SavePreparationAreaState(snapshot);
            _eventAggregator.Publish(new ChipPreparationStateChangedEventArgs(CloneSnapshot(snapshot)));
        }

        private static bool IsTransientStatus(ChipPreparationStatus status)
        {
            return status == ChipPreparationStatus.Preparing ||
                   status == ChipPreparationStatus.Loading ||
                   status == ChipPreparationStatus.Unloading ||
                   status == ChipPreparationStatus.Paused;
        }

        private static bool TryValidateActionRequest(ChipPreparationRequest request, out string rejectReason)
        {
            if (request == null)
            {
                rejectReason = "请求不能为空。";
                return false;
            }

            if (request.Action != ChipPreparationAction.Prepare &&
                request.Action != ChipPreparationAction.Load &&
                request.Action != ChipPreparationAction.Unload)
            {
                rejectReason = "芯片准备请求动作无效。";
                return false;
            }

            rejectReason = string.Empty;
            return true;
        }

        private static ChipPreparationStatus ResolveRunningStatus(ChipPreparationAction action)
        {
            if (action == ChipPreparationAction.Prepare)
            {
                return ChipPreparationStatus.Preparing;
            }

            if (action == ChipPreparationAction.Load)
            {
                return ChipPreparationStatus.Loading;
            }

            return ChipPreparationStatus.Unloading;
        }

        private static string ResolveStageForStatus(ChipPreparationStatus status)
        {
            switch (status)
            {
                case ChipPreparationStatus.Preparing:
                    return "Preparing";
                case ChipPreparationStatus.Prepared:
                    return "Prepared";
                case ChipPreparationStatus.Loading:
                    return "Loading";
                case ChipPreparationStatus.Loaded:
                    return "LoadedPendingTransfer";
                case ChipPreparationStatus.Unloading:
                    return "Unloading";
                case ChipPreparationStatus.Paused:
                    return "Paused";
                case ChipPreparationStatus.Faulted:
                    return "Faulted";
                default:
                    return "Idle";
            }
        }

        private static ChipPreparationStateSnapshot CreateIdleSnapshot(bool isChipLoaded)
        {
            return new ChipPreparationStateSnapshot
            {
                Status = ChipPreparationStatus.Idle,
                CurrentStage = isChipLoaded ? "LoadedPendingTransfer" : "Idle",
                LastUpdatedTime = DateTime.Now,
                CurrentAction = ChipPreparationAction.None,
                IsChipLoaded = isChipLoaded
            };
        }

        private static ChipPreparationStateSnapshot CreateRunningSnapshot(ChipPreparationRequest request, ChipPreparationStatus status, bool isChipLoaded)
        {
            return new ChipPreparationStateSnapshot
            {
                Status = status,
                ActiveRequestId = request != null ? request.RequestId : null,
                RecipeName = request != null ? request.RecipeName : null,
                SourceStepId = request != null ? request.SourceStepId : null,
                CurrentStage = ResolveStageForStatus(status),
                LastUpdatedTime = DateTime.Now,
                CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
                IsChipLoaded = isChipLoaded
            };
        }

        private static ChipPreparationStateSnapshot CreateStableSnapshot(ChipPreparationStatus status, ChipPreparationRequest request, bool isChipLoaded, string stage)
        {
            return new ChipPreparationStateSnapshot
            {
                Status = status,
                ActiveRequestId = request != null ? request.RequestId : null,
                RecipeName = request != null ? request.RecipeName : null,
                SourceStepId = request != null ? request.SourceStepId : null,
                CurrentStage = stage,
                LastUpdatedTime = DateTime.Now,
                CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
                IsChipLoaded = isChipLoaded
            };
        }

        private static ChipPreparationStateSnapshot CreateFaultedSnapshot(ChipPreparationRequest request, string errorMessage, bool isChipLoaded)
        {
            return new ChipPreparationStateSnapshot
            {
                Status = ChipPreparationStatus.Faulted,
                ActiveRequestId = request != null ? request.RequestId : null,
                RecipeName = request != null ? request.RecipeName : null,
                SourceStepId = request != null ? request.SourceStepId : null,
                CurrentStage = "Faulted",
                ErrorMessage = string.IsNullOrWhiteSpace(errorMessage) ? "芯片准备区执行失败。" : errorMessage,
                LastUpdatedTime = DateTime.Now,
                CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
                IsChipLoaded = isChipLoaded
            };
        }

        private static ChipPreparationRequest CloneRequest(ChipPreparationRequest request)
        {
            if (request == null)
            {
                return null;
            }

            return new ChipPreparationRequest
            {
                RequestId = request.RequestId,
                RecipeName = request.RecipeName,
                Action = request.Action,
                SourceStepId = request.SourceStepId
            };
        }

        private static ChipPreparationStateSnapshot CloneSnapshot(ChipPreparationStateSnapshot snapshot)
        {
            if (snapshot == null)
            {
                return null;
            }

            return new ChipPreparationStateSnapshot
            {
                Status = snapshot.Status,
                ActiveRequestId = snapshot.ActiveRequestId,
                RecipeName = snapshot.RecipeName,
                SourceStepId = snapshot.SourceStepId,
                CurrentStage = snapshot.CurrentStage,
                ErrorMessage = snapshot.ErrorMessage,
                LastUpdatedTime = snapshot.LastUpdatedTime,
                CurrentAction = snapshot.CurrentAction,
                IsChipLoaded = snapshot.IsChipLoaded
            };
        }

        private static ChipPreparationStateSnapshot RestoreSnapshot(PreparationAreaProcessState persistedState)
        {
            if (persistedState == null)
            {
                return CreateIdleSnapshot(false);
            }

            return new ChipPreparationStateSnapshot
            {
                Status = persistedState.Status,
                ActiveRequestId = persistedState.ActiveRequestId,
                RecipeName = persistedState.RecipeName,
                SourceStepId = persistedState.SourceStepId,
                CurrentStage = string.IsNullOrWhiteSpace(persistedState.CurrentStage)
                    ? ResolveStageForStatus(persistedState.Status)
                    : persistedState.CurrentStage,
                ErrorMessage = persistedState.ErrorMessage,
                LastUpdatedTime = persistedState.LastUpdatedTime == default(DateTime)
                    ? DateTime.Now
                    : persistedState.LastUpdatedTime,
                CurrentAction = persistedState.CurrentAction,
                IsChipLoaded = persistedState.HasPreparedChip
            };
        }
    }
}