using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Haoliang.Core.Services;
using Haoliang.Data.Repositories;

namespace Haoliang.Core.Services
{
    public interface IBackgroundTaskService
    {
        Task StartAsync(CancellationToken cancellationToken);
        Task StopAsync(CancellationToken cancellationToken);
    }

    public class BackgroundTaskService : BackgroundService, IBackgroundTaskService
    {
        private readonly ILogger<BackgroundTaskService> _logger;
        private readonly IDeviceCollectionService _collectionService;
        private readonly IProductionService _productionService;
        private readonly IAlarmService _alarmService;
        private readonly IRealTimeService _realTimeService;
        private readonly ISchedulerService _schedulerService;
        private readonly Timer _collectionTimer;
        private Timer _productionTimer;
        private Timer _alarmTimer;
        private Timer _realTimeTimer;
        private bool _isRunning;

        public BackgroundTaskService(
            ILogger<BackgroundTaskService> logger,
            IDeviceCollectionService collectionService,
            IProductionService productionService,
            IAlarmService alarmService,
            IRealTimeService realTimeService,
            ISchedulerService schedulerService)
        {
            _logger = logger;
            _collectionService = collectionService;
            _productionService = productionService;
            _alarmService = alarmService;
            _realTimeService = realTimeService;
            _schedulerService = schedulerService;
            
            _isRunning = false;
            _collectionTimer = new Timer(ExecuteCollectionTasks, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Background Task Service is starting.");
            
            _isRunning = true;
            
            try
            {
                await StartTimers(stoppingToken);
                
                while (!stoppingToken.IsCancellationRequested)
                {
                    await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
                    
                    // Log service health
                    await LogServiceHealthAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Background Task Service encountered an error.");
            }
            finally
            {
                await StopTimersAsync();
                _logger.LogInformation("Background Task Service is stopping.");
            }
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            if (_isRunning)
                return;

            _logger.LogInformation("Starting background task service...");
            
            try
            {
                // Start device collection
                await _collectionService.CollectAllDevicesAsync();
                _logger.LogInformation("Device collection started.");
                
                // Start production calculation
                await _productionService.CalculateAllProductionAsync();
                _logger.LogInformation("Production calculation started.");
                
                // Start alarm monitoring
                var activeAlarms = await _alarmService.GetActiveAlarmsAsync();
                if (activeAlarms.Any())
                {
                    _logger.LogInformation($"Found {activeAlarms.Count()} active alarms.");
                }
                
                _isRunning = true;
                _logger.LogInformation("Background task service started successfully.");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to start background task service.");
                throw;
            }
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            if (!_isRunning)
                return;

            _logger.LogInformation("Stopping background task service...");
            
            try
            {
                await StopTimersAsync();
                _isRunning = false;
                
                _logger.LogInformation("Background task service stopped successfully.");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error while stopping background task service.");
                throw;
            }
        }

        private async void ExecuteCollectionTasks(object state)
        {
            if (!_isRunning)
                return;

            try
            {
                await _collectionService.CollectAllDevicesAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing collection tasks.");
            }
        }

        private async Task StartTimers(CancellationToken cancellationToken)
        {
            // Start production calculation timer (every 5 minutes)
            _productionTimer = new Timer(async _ =>
            {
                if (!_isRunning) return;
                
                try
                {
                    await _productionService.CalculateAllProductionAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in production calculation timer.");
                }
            }, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

            // Start alarm monitoring timer (every 1 minute)
            _alarmTimer = new Timer(async _ =>
            {
                if (!_isRunning) return;
                
                try
                {
                    var activeAlarms = await _alarmService.GetActiveAlarmsAsync();
                    _logger.LogInformation($"Monitoring {activeAlarms.Count()} active alarms.");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in alarm monitoring timer.");
                }
            }, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));

            // Start real-time data push timer (every 30 seconds)
            _realTimeTimer = new Timer(async _ =>
            {
                if (!_isRunning) return;
                
                try
                {
                    await _realTimeService.BroadcastDeviceStatusAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in real-time data push timer.");
                }
            }, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));

            _logger.LogInformation("Background timers started.");
        }

        private async Task StopTimersAsync()
        {
            _collectionTimer?.Dispose();
            _productionTimer?.Dispose();
            _alarmTimer?.Dispose();
            _realTimeTimer?.Dispose();
            
            _logger.LogInformation("Background timers stopped.");
        }

        private async Task LogServiceHealthAsync()
        {
            try
            {
                var collectionHealth = await _collectionService.GetCollectionHealthAsync();
                var deviceCount = await _collectionService.GetCollectionStatisticsAsync(DateTime.Today);
                
                _logger.LogInformation($"Service Health - Devices: {collectionHealth.TotalDevices}, " +
                                    $"Online: {collectionHealth.OnlineDevices}, " +
                                    $"Success Rate: {collectionHealth.SuccessRate:F1}%, " +
                                    $"Active Tasks: {collectionHealth.ActiveCollectionTasks}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error logging service health.");
            }
        }
    }

    public interface ISchedulerService
    {
        Task ScheduleDeviceCollectionAsync(int deviceId);
        Task ScheduleProductionCalculationAsync(int deviceId);
        Task ScheduleAlarmCheckAsync();
        Task CancelScheduledTaskAsync(string taskId);
        Task<IEnumerable<ScheduledTask>> GetScheduledTasksAsync();
    }

    public class BackgroundTaskManager : ISchedulerService
    {
        private readonly ILogger<BackgroundTaskManager> _logger;
        private readonly IDeviceCollectionService _collectionService;
        private readonly IProductionService _productionService;
        private readonly IAlarmService _alarmService;
        private readonly Dictionary<string, Timer> _scheduledTasks = new Dictionary<string, Timer>();
        private readonly object _lock = new object();

        public BackgroundTaskManager(
            ILogger<BackgroundTaskManager> logger,
            IDeviceCollectionService collectionService,
            IProductionService productionService,
            IAlarmService alarmService)
        {
            _logger = logger;
            _collectionService = collectionService;
            _productionService = productionService;
            _alarmService = alarmService;
        }

        public async Task ScheduleDeviceCollectionAsync(int deviceId)
        {
            var taskId = $"collection_{deviceId}_{DateTime.Now:yyyyMMddHHmmss}";
            
            lock (_lock)
            {
                if (_scheduledTasks.ContainsKey(taskId))
                {
                    _scheduledTasks[taskId].Dispose();
                }

                var timer = new Timer(async _ =>
                {
                    try
                    {
                        await _collectionService.CollectDeviceAsync(deviceId);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"Failed to execute scheduled collection for device {deviceId}");
                    }
                }, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

                _scheduledTasks[taskId] = timer;
            }

            _logger.LogInformation($"Scheduled device collection for device {deviceId} with task ID {taskId}");
        }

        public async Task ScheduleProductionCalculationAsync(int deviceId)
        {
            var taskId = $"production_{deviceId}_{DateTime.Now:yyyyMMddHHmmss}";
            
            lock (_lock)
            {
                if (_scheduledTasks.ContainsKey(taskId))
                {
                    _scheduledTasks[taskId].Dispose();
                }

                var timer = new Timer(async _ =>
                {
                    try
                    {
                        await _productionService.CalculateProductionAsync(deviceId);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"Failed to execute scheduled production calculation for device {deviceId}");
                    }
                }, null, TimeSpan.Zero, TimeSpan.FromMinutes(10));

                _scheduledTasks[taskId] = timer;
            }

            _logger.LogInformation($"Scheduled production calculation for device {deviceId} with task ID {taskId}");
        }

        public async Task ScheduleAlarmCheckAsync()
        {
            var taskId = $"alarm_check_{DateTime.Now:yyyyMMddHHmmss}";
            
            lock (_lock)
            {
                if (_scheduledTasks.ContainsKey(taskId))
                {
                    _scheduledTasks[taskId].Dispose();
                }

                var timer = new Timer(async _ =>
                {
                    try
                    {
                        var activeAlarms = await _alarmService.GetActiveAlarmsAsync();
                        _logger.LogInformation($"Alarm check completed: {activeAlarms.Count()} active alarms");
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Failed to execute alarm check");
                    }
                }, null, TimeSpan.Zero, TimeSpan.FromMinutes(2));

                _scheduledTasks[taskId] = timer;
            }

            _logger.LogInformation($"Scheduled alarm check with task ID {taskId}");
        }

        public Task CancelScheduledTaskAsync(string taskId)
        {
            lock (_lock)
            {
                if (_scheduledTasks.TryGetValue(taskId, out var timer))
                {
                    timer.Dispose();
                    _scheduledTasks.Remove(taskId);
                    _logger.LogInformation($"Cancelled scheduled task {taskId}");
                    return Task.CompletedTask;
                }
            }

            _logger.LogWarning($"Attempted to cancel non-existent task {taskId}");
            return Task.CompletedTask;
        }

        public Task<IEnumerable<ScheduledTask>> GetScheduledTasksAsync()
        {
            var tasks = _scheduledTasks.Keys.Select(key => new ScheduledTask
            {
                TaskId = key,
                ScheduledTime = DateTime.Now,
                Status = "Active"
            }).ToList();

            return Task.FromResult<IEnumerable<ScheduledTask>>(tasks);
        }
    }

    public class ScheduledTask
    {
        public string TaskId { get; set; }
        public DateTime ScheduledTime { get; set; }
        public string Status { get; set; }
    }
}