using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Haoliang.Core.Services;
using Haoliang.Models.Device;
using Haoliang.Models.System;
using Haoliang.Models.Common;

namespace Haoliang.Core.Services
{
    public interface IDeviceStateMachine
    {
        /// <summary>
        /// Get current state of device
        /// </summary>
        DeviceState GetCurrentState(int deviceId);

        /// <summary>
        /// Check if device can transition to target state
        /// </summary>
        Task<bool> CanTransitionAsync(int deviceId, DeviceState targetState);

        /// <summary>
        /// Transition device to new state
        /// </summary>
        Task<DeviceStateTransitionResult> TransitionToStateAsync(int deviceId, DeviceState targetState, object context = null);

        /// <summary>
        /// Trigger device event
        /// </summary>
        Task<DeviceStateTransitionResult> TriggerEventAsync(int deviceId, DeviceEvent deviceEvent, object context = null);

        /// <summary>
        /// Get device state history
        /// </summary>
        Task<List<DeviceStateHistory>> GetStateHistoryAsync(int deviceId, DateTime? startDate = null, DateTime? endDate = null);

        /// <summary>
        /// Get device state statistics
        /// </summary>
        Task<DeviceStateStatistics> GetStateStatisticsAsync(int deviceId, DateTime? startDate = null, DateTime? endDate = null);

        /// <summary>
        /// Force device to specific state
        /// </summary>
        Task<DeviceStateTransitionResult> ForceStateAsync(int deviceId, DeviceState targetState, string reason);

        /// <summary>
        /// Validate device state
        /// </summary>
        Task<DeviceValidationResult> ValidateStateAsync(int deviceId);

        /// <summary>
        /// Register state change handler
        /// </summary>
        void RegisterStateHandler(StateChangeHandler handler);

        /// <summary>
        /// Unregister state change handler
        /// </summary>
        void UnregisterStateHandler(StateChangeHandler handler);
    }

    public class DeviceStateMachine : IDeviceStateMachine, IHostedService
    {
        private readonly IDeviceRepository _deviceRepository;
        private readonly IDeviceCollectionService _collectionService;
        private readonly IAlarmService _alarmService;
        private readonly ICacheService _cacheService;
        private readonly Timer _stateCheckTimer;
        private readonly ConcurrentDictionary<int, DeviceStateContext> _deviceStates = new ConcurrentDictionary<int, DeviceStateContext>();
        private readonly List<StateChangeHandler> _stateHandlers = new List<StateChangeHandler>();
        private readonly object _lock = new object();

        public DeviceStateMachine(
            IDeviceRepository deviceRepository,
            IDeviceCollectionService collectionService,
            IAlarmService alarmService,
            ICacheService cacheService)
        {
            _deviceRepository = deviceRepository;
            _collectionService = collectionService;
            _alarmService = alarmService;
            _cacheService = cacheService;

            // Start timer for periodic state checks
            _stateCheckTimer = new Timer(CheckDeviceStates, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
        }

        public DeviceState GetCurrentState(int deviceId)
        {
            if (_deviceStates.TryGetValue(deviceId, out var context))
            {
                return context.CurrentState;
            }
            return DeviceState.Unknown;
        }

        public async Task<bool> CanTransitionAsync(int deviceId, DeviceState targetState)
        {
            var currentState = GetCurrentState(deviceId);
            return await CanTransitionFromAsync(currentState, targetState, deviceId);
        }

        public async Task<DeviceStateTransitionResult> TransitionToStateAsync(int deviceId, DeviceState targetState, object context = null)
        {
            var result = new DeviceStateTransitionResult
            {
                DeviceId = deviceId,
                FromState = GetCurrentState(deviceId),
                ToState = targetState,
                Success = false,
                Message = "",
                Timestamp = DateTime.UtcNow
            };

            try
            {
                // Validate transition
                if (!await CanTransitionAsync(deviceId, targetState))
                {
                    result.Message = $"Cannot transition from {result.FromState} to {targetState}";
                    return result;
                }

                // Get device
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null)
                {
                    result.Message = "Device not found";
                    return result;
                }

                // Create transition context
                var transitionContext = new DeviceStateTransitionContext
                {
                    DeviceId = deviceId,
                    Device = device,
                    FromState = result.FromState,
                    ToState = targetState,
                    Context = context,
                    Timestamp = DateTime.UtcNow
                };

                // Execute exit actions for current state
                var exitResult = await ExecuteStateActionsAsync(deviceId, result.FromState, transitionContext, true);
                if (!exitResult.Success)
                {
                    result.Message = $"Failed to exit {result.FromState}: {exitResult.Message}";
                    return result;
                }

                // Execute enter actions for target state
                var enterResult = await ExecuteStateActionsAsync(deviceId, targetState, transitionContext, false);
                if (!enterResult.Success)
                {
                    result.Message = $"Failed to enter {targetState}: {enterResult.Message}";
                    // Attempt to revert to original state
                    await ExecuteStateActionsAsync(deviceId, result.FromState, transitionContext, true);
                    return result;
                }

                // Update device state
                lock (_lock)
                {
                    var deviceContext = _deviceStates.GetOrAdd(deviceId, new DeviceStateContext
                    {
                        CurrentState = targetState,
                        PreviousState = result.FromState,
                        StateChangedAt = DateTime.UtcNow,
                        Context = context
                    });

                    deviceContext.CurrentState = targetState;
                    deviceContext.PreviousState = result.FromState;
                    deviceContext.StateChangedAt = DateTime.UtcNow;
                    deviceContext.Context = context;
                }

                // Record state change in history
                await RecordStateChangeAsync(deviceId, result.FromState, targetState, context);

                // Notify handlers
                await NotifyStateHandlersAsync(deviceId, result.FromState, targetState, transitionContext);

                // Update device status
                await UpdateDeviceStatusAsync(device, targetState);

                result.Success = true;
                result.Message = $"Successfully transitioned from {result.FromState} to {targetState}";
            }
            catch (Exception ex)
            {
                result.Message = $"Error during state transition: {ex.Message}";
            }

            return result;
        }

        public async Task<DeviceStateTransitionResult> TriggerEventAsync(int deviceId, DeviceEvent deviceEvent, object context = null)
        {
            var currentState = GetCurrentState(deviceId);
            var eventConfig = GetEventConfiguration(deviceEvent, currentState);

            if (eventConfig == null)
            {
                return new DeviceStateTransitionResult
                {
                    DeviceId = deviceId,
                    FromState = currentState,
                    ToState = currentState,
                    Success = false,
                    Message = $"No event handler configured for {deviceEvent} in state {currentState}",
                    Timestamp = DateTime.UtcNow
                };
            }

            // Check event conditions
            if (!await EvaluateEventConditionsAsync(deviceId, deviceEvent, eventConfig.Conditions))
            {
                return new DeviceStateTransitionResult
                {
                    DeviceId = deviceId,
                    FromState = currentState,
                    ToState = currentState,
                    Success = false,
                    Message = $"Event conditions not met for {deviceEvent}",
                    Timestamp = DateTime.UtcNow
                };
            }

            // Transition to target state
            return await TransitionToStateAsync(deviceId, eventConfig.TargetState, context);
        }

        public async Task<List<DeviceStateHistory>> GetStateHistoryAsync(int deviceId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var history = await _deviceRepository.GetDeviceStateHistoryAsync(deviceId, startDate, endDate);
            
            // Add current state if not in history
            if (!history.Any(h => h.State == GetCurrentState(deviceId)))
            {
                history.Add(new DeviceStateHistory
                {
                    DeviceId = deviceId,
                    State = GetCurrentState(deviceId),
                    ChangedAt = DateTime.UtcNow,
                    ChangedBy = "System",
                    Notes = "Current state"
                });
            }

            return history.OrderBy(h => h.ChangedAt).ToList();
        }

        public async Task<DeviceStateStatistics> GetStateStatisticsAsync(int deviceId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var history = await GetStateHistoryAsync(deviceId, startDate, endDate);
            var statistics = new DeviceStateStatistics
            {
                DeviceId = deviceId,
                PeriodStart = startDate ?? DateTime.UtcNow.AddDays(-7),
                PeriodEnd = endDate ?? DateTime.UtcNow,
                StateTransitions = history.Count - 1, // Excluding initial state
                StateDurations = new Dictionary<DeviceState, TimeSpan>(),
                StateCounts = new Dictionary<DeviceState, int>(),
                LastStateChange = history.LastOrDefault()?.ChangedAt
            };

            // Calculate state durations
            for (int i = 0; i < history.Count - 1; i++)
            {
                var fromState = history[i].State;
                var toState = history[i + 1].State;
                var duration = history[i + 1].ChangedAt - history[i].ChangedAt;

                if (!statistics.StateDurations.ContainsKey(fromState))
                {
                    statistics.StateDurations[fromState] = TimeSpan.Zero;
                }
                statistics.StateDurations[fromState] += duration;

                if (!statistics.StateCounts.ContainsKey(fromState))
                {
                    statistics.StateCounts[fromState] = 0;
                }
                statistics.StateCounts[fromState]++;
            }

            // Add current state duration
            if (history.Any())
            {
                var currentState = GetCurrentState(deviceId);
                var lastState = history.Last();
                var currentDuration = DateTime.UtcNow - lastState.ChangedAt;

                if (!statistics.StateDurations.ContainsKey(currentState))
                {
                    statistics.StateDurations[currentState] = TimeSpan.Zero;
                }
                statistics.StateDurations[currentState] += currentDuration;

                if (!statistics.StateCounts.ContainsKey(currentState))
                {
                    statistics.StateCounts[currentState] = 0;
                }
                statistics.StateCounts[currentState]++;
            }

            return statistics;
        }

        public async Task<DeviceStateTransitionResult> ForceStateAsync(int deviceId, DeviceState targetState, string reason)
        {
            // Create force transition context
            var forceContext = new { Forced = true, Reason = reason };

            var result = await TransitionToStateAsync(deviceId, targetState, forceContext);
            
            if (!result.Success)
            {
                // If normal transition fails, create a force entry in history
                await RecordStateChangeAsync(deviceId, GetCurrentState(deviceId), targetState, forceContext, true);
                
                // Update in-memory state
                lock (_lock)
                {
                    var deviceContext = _deviceStates.GetOrAdd(deviceId, new DeviceStateContext());
                    deviceContext.CurrentState = targetState;
                    deviceContext.PreviousState = GetCurrentState(deviceId);
                    deviceContext.StateChangedAt = DateTime.UtcNow;
                    deviceContext.Context = forceContext;
                }

                result.Success = true;
                result.Message = $"Forced state transition to {targetState}: {reason}";
            }

            return result;
        }

        public async Task<DeviceValidationResult> ValidateStateAsync(int deviceId)
        {
            var result = new DeviceValidationResult
            {
                DeviceId = deviceId,
                IsValid = true,
                Issues = new List<string>(),
                CurrentState = GetCurrentState(deviceId),
                Timestamp = DateTime.UtcNow
            };

            try
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null)
                {
                    result.IsValid = false;
                    result.Issues.Add("Device not found");
                    return result;
                }

                // Check if device state matches actual status
                var actualStatus = await _collectionService.GetDeviceCurrentStatusAsync(deviceId);
                var expectedState = TranslateStatusToDeviceState(actualStatus);

                if (expectedState != result.CurrentState)
                {
                    result.IsValid = false;
                    result.Issues.Add($"State mismatch: expected {expectedState}, actual {result.CurrentState}");
                }

                // Validate state-specific rules
                var stateValidation = await ValidateStateRulesAsync(deviceId, result.CurrentState);
                if (!stateValidation.IsValid)
                {
                    result.IsValid = false;
                    result.Issues.AddRange(stateValidation.Issues);
                }

                // Check for state timeouts
                var stateTimeout = await CheckStateTimeoutAsync(deviceId, result.CurrentState);
                if (stateTimeout.IsTimeout)
                {
                    result.IsValid = false;
                    result.Issues.Add($"State timeout: {result.CurrentState} exceeded maximum duration");
                }
            }
            catch (Exception ex)
            {
                result.IsValid = false;
                result.Issues.Add($"Validation error: {ex.Message}");
            }

            return result;
        }

        public void RegisterStateHandler(StateChangeHandler handler)
        {
            lock (_lock)
            {
                _stateHandlers.Add(handler);
            }
        }

        public void UnregisterStateHandler(StateChangeHandler handler)
        {
            lock (_lock)
            {
                _stateHandlers.Remove(handler);
            }
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            // Initialize device states
            return InitializeDeviceStatesAsync();
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _stateCheckTimer?.Dispose();
            return Task.CompletedTask;
        }

        #region Private Methods

        private async Task InitializeDeviceStatesAsync()
        {
            var devices = await _deviceRepository.GetAllDevicesAsync();
            
            foreach (var device in devices)
            {
                var stateContext = new DeviceStateContext
                {
                    CurrentState = DeviceState.Unknown,
                    PreviousState = DeviceState.Unknown,
                    StateChangedAt = DateTime.UtcNow,
                    Context = null
                };

                // Get current device status to determine state
                var status = await _collectionService.GetDeviceCurrentStatusAsync(device.Id);
                stateContext.CurrentState = TranslateStatusToDeviceState(status);

                _deviceStates.AddOrUpdate(device.Id, stateContext, (key, existing) => stateContext);
            }
        }

        private async Task CheckDeviceStates(object state)
        {
            try
            {
                var devices = await _deviceRepository.GetAllActiveDevicesAsync();
                
                foreach (var device in devices)
                {
                    var validationResult = await ValidateStateAsync(device.Id);
                    if (!validationResult.IsValid)
                    {
                        // Handle invalid state
                        await HandleInvalidStateAsync(device.Id, validationResult);
                    }

                    // Check for state timeouts
                    var stateTimeout = await CheckStateTimeoutAsync(device.Id, GetCurrentState(device.Id));
                    if (stateTimeout.IsTimeout)
                    {
                        await HandleStateTimeoutAsync(device.Id, stateTimeout);
                    }
                }
            }
            catch (Exception ex)
            {
                // Log error
                Console.WriteLine($"Error checking device states: {ex.Message}");
            }
        }

        private async Task<DeviceStateTransitionResult> ExecuteStateActionsAsync(
            int deviceId, 
            DeviceState state, 
            DeviceStateTransitionContext context, 
            bool isExit)
        {
            var actions = isExit ? GetExitActions(state) : GetEnterActions(state);
            
            foreach (var action in actions)
            {
                try
                {
                    var result = await action.ExecuteAsync(deviceId, context);
                    if (!result.Success)
                    {
                        return new DeviceStateTransitionResult
                        {
                            DeviceId = deviceId,
                            FromState = context.FromState,
                            ToState = context.ToState,
                            Success = false,
                            Message = result.Message,
                            Timestamp = DateTime.UtcNow
                        };
                    }
                }
                catch (Exception ex)
                {
                    return new DeviceStateTransitionResult
                    {
                        DeviceId = deviceId,
                        FromState = context.FromState,
                        ToState = context.ToState,
                        Success = false,
                        Message = $"Error executing action: {ex.Message}",
                        Timestamp = DateTime.UtcNow
                    };
                }
            }

            return new DeviceStateTransitionResult
            {
                DeviceId = deviceId,
                FromState = context.FromState,
                ToState = context.ToState,
                Success = true,
                Message = "Actions executed successfully",
                Timestamp = DateTime.UtcNow
            };
        }

        private List<StateAction> GetExitActions(DeviceState state)
        {
            return GetStateActions(state, "exit");
        }

        private List<StateAction> GetEnterActions(DeviceState state)
        {
            return GetStateActions(state, "enter");
        }

        private List<StateAction> GetStateActions(DeviceState state, string actionType)
        {
            // This would typically come from configuration or database
            // For now, return basic actions
            var actions = new List<StateAction>();
            
            switch (state)
            {
                case DeviceState.Running:
                    if (actionType == "exit")
                    {
                        actions.Add(new StopProductionAction());
                    }
                    else
                    {
                        actions.Add(new StartProductionAction());
                    }
                    break;
                    
                case DeviceState.Idle:
                    if (actionType == "enter")
                    {
                        actions.Add(new LogIdleAction());
                    }
                    break;
                    
                case DeviceState.Error:
                    if (actionType == "enter")
                    {
                        actions.Add(new NotifyErrorAction());
                    }
                    break;
                    
                default:
                    actions.Add(new LogStateAction(actionType, state));
                    break;
            }
            
            return actions;
        }

        private async Task<bool> CanTransitionFromAsync(DeviceState fromState, DeviceState targetState, int deviceId)
        {
            var allowedTransitions = GetAllowedTransitions(fromState);
            return allowedTransitions.Contains(targetState);
        }

        private List<DeviceState> GetAllowedTransitions(DeviceState fromState)
        {
            // Define state transition rules
            var transitions = new Dictionary<DeviceState, List<DeviceState>>
            {
                [DeviceState.Unknown] = new List<DeviceState> { DeviceState.Offline, DeviceState.Idle },
                [DeviceState.Offline] = new List<DeviceState> { DeviceState.Online, DeviceState.Unknown },
                [DeviceState.Online] = new List<DeviceState> { DeviceState.Idle, DeviceState.Running, DeviceState.Error, DeviceState.Maintenance },
                [DeviceState.Idle] = new List<DeviceState> { DeviceState.Running, DeviceState.Offline, DeviceState.Maintenance },
                [DeviceState.Running] = new List<DeviceState> { DeviceState.Idle, DeviceState.Error, DeviceState.Stopped, DeviceState.Maintenance },
                [DeviceState.Error] = new List<DeviceState> { DeviceState.Idle, DeviceState.Maintenance, DeviceState.Unknown },
                [DeviceState.Maintenance] = new List<DeviceState> { DeviceState.Idle, DeviceState.Offline, DeviceState.Unknown },
                [DeviceState.Stopped] = new List<DeviceState> { DeviceState.Idle, DeviceState.Offline }
            };

            return transitions.GetValueOrDefault(fromState, new List<DeviceState>());
        }

        private EventConfig GetEventConfiguration(DeviceEvent deviceEvent, DeviceState currentState)
        {
            // This would typically come from configuration
            var eventConfigs = new Dictionary<(DeviceEvent, DeviceState), EventConfig>
            {
                [(DeviceEvent.Start, DeviceState.Idle)] = new EventConfig
                {
                    TargetState = DeviceState.Running,
                    Conditions = new List<Func<int, Task<bool>>>
                    {
                        async deviceId => await IsDeviceReadyForProduction(deviceId)
                    }
                },
                
                [(DeviceEvent.Stop, DeviceState.Running)] = new EventConfig
                {
                    TargetState = DeviceState.Idle,
                    Conditions = new List<Func<int, Task<bool>>>
                    {
                        async deviceId => await IsProductionComplete(deviceId)
                    }
                },
                
                [(DeviceEvent.Error, DeviceState.Running)] = new EventConfig
                {
                    TargetState = DeviceState.Error,
                    Conditions = new List<Func<int, Task<bool>>>
                    {
                        async deviceId => await HasDeviceError(deviceId)
                    }
                },
                
                [(DeviceEvent.Resume, DeviceState.Maintenance)] = new EventConfig
                {
                    TargetState = DeviceState.Idle,
                    Conditions = new List<Func<int, Task<bool>>>
                    {
                        async deviceId => await IsMaintenanceComplete(deviceId)
                    }
                }
            };

            return eventConfigs.GetValueOrDefault((deviceEvent, currentState));
        }

        private async Task<bool> EvaluateEventConditionsAsync(int deviceId, DeviceEvent deviceEvent, List<Func<int, Task<bool>>> conditions)
        {
            if (conditions == null || !conditions.Any())
                return true;

            foreach (var condition in conditions)
            {
                var conditionResult = await condition(deviceId);
                if (!conditionResult)
                    return false;
            }

            return true;
        }

        private async Task RecordStateChangeAsync(int deviceId, DeviceState fromState, DeviceState toState, object context, bool isForced = false)
        {
            var history = new DeviceStateHistory
            {
                DeviceId = deviceId,
                FromState = fromState,
                ToState = toState,
                ChangedAt = DateTime.UtcNow,
                ChangedBy = isForced ? "System (Forced)" : "System",
                Notes = isForced ? $"Forced transition: {JsonSerializer(context)}" : JsonSerializer(context)
            };

            await _deviceRepository.AddDeviceStateHistoryAsync(history);
        }

        private async Task NotifyStateHandlersAsync(int deviceId, DeviceState fromState, DeviceState toState, DeviceStateTransitionContext context)
        {
            var handlersCopy = _stateHandlers.ToList(); // Copy to avoid modification during iteration
            
            foreach (var handler in handlersCopy)
            {
                try
                {
                    await handler(deviceId, fromState, toState, context);
                }
                catch (Exception ex)
                {
                    // Log error but continue with other handlers
                    Console.WriteLine($"Error in state handler: {ex.Message}");
                }
            }
        }

        private async Task UpdateDeviceStatusAsync(CNCDevice device, DeviceState state)
        {
            // Update device status in database
            device.Status = TranslateStateToDeviceStatus(state);
            await _deviceRepository.UpdateDeviceAsync(device);

            // Update cache
            _cacheService.InvalidateDeviceCache(device.Id);
        }

        private DeviceState TranslateStatusToDeviceState(DeviceCurrentStatus status)
        {
            if (status == null || status.Status == DeviceStatus.Unknown)
                return DeviceState.Unknown;

            return status.Status switch
            {
                DeviceStatus.Offline => DeviceState.Offline,
                DeviceStatus.Online => DeviceState.Online,
                DeviceStatus.Idle => DeviceState.Idle,
                DeviceStatus.Running => DeviceState.Running,
                DeviceStatus.Error => DeviceState.Error,
                DeviceStatus.Maintenance => DeviceState.Maintenance,
                DeviceStatus.Stopped => DeviceState.Stopped,
                _ => DeviceState.Unknown
            };
        }

        private DeviceStatus TranslateStateToDeviceStatus(DeviceState state)
        {
            return state switch
            {
                DeviceState.Offline => DeviceStatus.Offline,
                DeviceState.Online => DeviceStatus.Online,
                DeviceState.Idle => DeviceStatus.Idle,
                DeviceState.Running => DeviceStatus.Running,
                DeviceState.Error => DeviceStatus.Error,
                DeviceState.Maintenance => DeviceStatus.Maintenance,
                DeviceState.Stopped => DeviceStatus.Stopped,
                _ => DeviceStatus.Unknown
            };
        }

        private async Task<DeviceValidationResult> ValidateStateRulesAsync(int deviceId, DeviceState state)
        {
            var result = new DeviceValidationResult { IsValid = true, Issues = new List<string>() };

            switch (state)
            {
                case DeviceState.Running:
                    // Check if device should actually be running
                    var device = await _deviceRepository.GetByIdAsync(deviceId);
                    if (device != null && device.EnableProduction)
                    {
                        var status = await _collectionService.GetDeviceCurrentStatusAsync(deviceId);
                        if (status.Status != DeviceStatus.Running)
                        {
                            result.IsValid = false;
                            result.Issues.Add("Device is in Running state but actual status is not Running");
                        }
                    }
                    break;

                case DeviceState.Error:
                    // Check if device has active errors
                    var activeAlarms = await _alarmService.GetActiveAlertsByDeviceAsync(deviceId);
                    if (!activeAlarms.Any(a => a.AlertType == "DeviceError"))
                    {
                        result.IsValid = false;
                        result.Issues.Add("Device is in Error state but has no active error alerts");
                    }
                    break;
            }

            return result;
        }

        private async Task<StateTimeoutInfo> CheckStateTimeoutAsync(int deviceId, DeviceState state)
        {
            var stateContext = _deviceStates.GetValueOrDefault(deviceId);
            if (stateContext == null)
                return new StateTimeoutInfo { IsTimeout = false };

            var stateDurations = GetStateTimeoutDurations();
            var maxDuration = stateDurations.GetValueOrDefault(state, TimeSpan.FromMinutes(30));

            var currentDuration = DateTime.UtcNow - stateContext.StateChangedAt;
            
            return new StateTimeoutInfo
            {
                IsTimeout = currentDuration > maxDuration,
                State = state,
                CurrentDuration = currentDuration,
                MaxDuration = maxDuration,
                ExceededBy = currentDuration - maxDuration
            };
        }

        private Dictionary<DeviceState, TimeSpan> GetStateTimeoutDurations()
        {
            return new Dictionary<DeviceState, TimeSpan>
            {
                [DeviceState.Unknown] = TimeSpan.FromMinutes(5),
                [DeviceState.Offline] = TimeSpan.FromHours(1),
                [DeviceState.Online] = TimeSpan.FromMinutes(15),
                [DeviceState.Idle] = TimeSpan.FromMinutes(10),
                [DeviceState.Running] = TimeSpan.FromHours(8),
                [DeviceState.Error] = TimeSpan.FromMinutes(60),
                [DeviceState.Maintenance] = TimeSpan.FromHours(4),
                [DeviceState.Stopped] = TimeSpan.FromMinutes(30)
            };
        }

        private async Task HandleInvalidStateAsync(int deviceId, DeviceValidationResult validationResult)
        {
            // Log warning
            Console.WriteLine($"Device {deviceId} state validation failed: {string.Join(", ", validationResult.Issues)}");

            // Attempt to transition to a safe state
            var safeState = DetermineSafeState(deviceId, validationResult.CurrentState);
            await ForceStateAsync(deviceId, safeState, $"State validation failed: {string.Join(", ", validationResult.Issues)}");
        }

        private async Task HandleStateTimeoutAsync(int deviceId, StateTimeoutInfo timeoutInfo)
        {
            // Log warning
            Console.WriteLine($"Device {deviceId} state {timeoutInfo.State} exceeded maximum duration by {timeoutInfo.ExceededBy}");

            // Trigger timeout event
            await TriggerEventAsync(deviceId, DeviceEvent.Timeout, timeoutInfo);
        }

        private DeviceState DetermineSafeState(int deviceId, DeviceState currentState)
        {
            return DeviceState.Idle; // Default safe state
        }

        private async Task<bool> IsDeviceReadyForProduction(int deviceId)
        {
            // Check if device is ready for production
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            var status = await _collectionService.GetDeviceCurrentStatusAsync(deviceId);
            
            return device != null && device.EnableProduction && 
                   status.Status == DeviceStatus.Online && 
                   !device.IsUnderMaintenance;
        }

        private async Task<bool> IsProductionComplete(int deviceId)
        {
            // Check if production is complete
            var records = await _deviceRepository.GetProductionRecordsByDeviceAsync(deviceId);
            return records.Any() && records.Last().IsComplete;
        }

        private async Task<bool> HasDeviceError(int deviceId)
        {
            // Check if device has errors
            var alerts = await _alarmService.GetActiveAlertsByDeviceAsync(deviceId);
            return alerts.Any(a => a.AlertType == "DeviceError");
        }

        private async Task<bool> IsMaintenanceComplete(int deviceId)
        {
            // Check if maintenance is complete
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            return device != null && !device.IsUnderMaintenance;
        }

        private string JsonSerializer(object obj)
        {
            // Simplified JSON serialization
            return obj?.ToString() ?? "{}";
        }

        #endregion
    }

    #region Supporting Classes and Interfaces

    public delegate Task StateChangeHandler(int deviceId, DeviceState fromState, DeviceState toState, DeviceStateTransitionContext context);

    public interface IStateAction
    {
        Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context);
    }

    public class StateActionResult
    {
        public bool Success { get; set; }
        public string Message { get; set; }
    }

    public class DeviceStateContext
    {
        public DeviceState CurrentState { get; set; }
        public DeviceState PreviousState { get; set; }
        public DateTime StateChangedAt { get; set; }
        public object Context { get; set; }
    }

    public class DeviceStateTransitionContext
    {
        public int DeviceId { get; set; }
        public CNCDevice Device { get; set; }
        public DeviceState FromState { get; set; }
        public DeviceState ToState { get; set; }
        public object Context { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class EventConfig
    {
        public DeviceState TargetState { get; set; }
        public List<Func<int, Task<bool>>> Conditions { get; set; }
    }

    public class StateTimeoutInfo
    {
        public bool IsTimeout { get; set; }
        public DeviceState State { get; set; }
        public TimeSpan CurrentDuration { get; set; }
        public TimeSpan MaxDuration { get; set; }
        public TimeSpan ExceededBy { get; set; }
    }

    public class DeviceValidationResult
    {
        public int DeviceId { get; set; }
        public bool IsValid { get; set; }
        public List<string> Issues { get; set; }
        public DeviceState CurrentState { get; set; }
        public DateTime Timestamp { get; set; }
    }

    #endregion

    #region State Action Implementations

    public class StopProductionAction : IStateAction
    {
        public async Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context)
        {
            // Implementation to stop production
            return new StateActionResult { Success = true, Message = "Production stopped" };
        }
    }

    public class StartProductionAction : IStateAction
    {
        public async Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context)
        {
            // Implementation to start production
            return new StateActionResult { Success = true, Message = "Production started" };
        }
    }

    public class LogIdleAction : IStateAction
    {
        public async Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context)
        {
            // Implementation to log idle state
            return new StateActionResult { Success = true, Message = "Idle state logged" };
        }
    }

    public class NotifyErrorAction : IStateAction
    {
        public async Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context)
        {
            // Implementation to notify about error
            return new StateActionResult { Success = true, Message = "Error notification sent" };
        }
    }

    public class LogStateAction : IStateAction
    {
        private readonly string _actionType;
        private readonly DeviceState _state;

        public LogStateAction(string actionType, DeviceState state)
        {
            _actionType = actionType;
            _state = state;
        }

        public async Task<StateActionResult> ExecuteAsync(int deviceId, DeviceStateTransitionContext context)
        {
            // Implementation to log state changes
            return new StateActionResult { Success = true, Message = $"{_actionType} action for {_state} logged" };
        }
    }

    #endregion
}