using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Haoliang.Models.Production;
using Haoliang.Models.Device;
using Haoliang.Models.DataCollection;
using Haoliang.Data.Repositories;
using Haoliang.Core.Services;

namespace Haoliang.Core.Services
{
    public interface IProductionCalculator
    {
        Task<int> CalculateProductionAsync(DeviceCurrentStatus current, DeviceCurrentStatus last);
        Task<int> CalculateProgramSwitchProductionAsync(DeviceCurrentStatus current, DeviceCurrentStatus last);
        Task<bool> IsNewProgramAsync(string currentProgram, string lastProgram);
        Task HandleCrossDayResetAsync(DeviceCurrentStatus current, DeviceCurrentStatus last);
        Task<int> ValidateProductionValueAsync(int quantity, DeviceCurrentStatus current);
        Task<ProductionRecord> CreateProductionRecordAsync(int deviceId, DeviceCurrentStatus current, DeviceCurrentStatus last, int quantity);
    }

    public interface IProductionService
    {
        Task CalculateProductionAsync(int deviceId);
        Task CalculateAllProductionAsync();
        Task<ProductionRecord> GetTodayProductionAsync(int deviceId);
        Task<IEnumerable<ProductionRecord>> GetProductionByDateAsync(int deviceId, DateTime date);
        Task<ProductionStatistics> GetProductionStatisticsAsync(int deviceId, DateTime date);
        Task<ProductionSummary> GetProductionSummaryAsync(DateTime date);
        Task<decimal> GetQualityRateAsync(int deviceId, DateTime date);
        Task<bool> HasProductionDataAsync(int deviceId, DateTime date);
        Task ArchiveProductionDataAsync(int daysToKeep = 90);
    }

    public interface IProductionScheduler
    {
        Task StartProductionCalculationAsync();
        Task StopProductionCalculationAsync();
        Task ScheduleProductionCalculationAsync(int deviceId);
        Task<DateTime> GetNextCalculationTimeAsync();
        Task<bool> IsCalculationRunningAsync();
    }

    public class ProductionCalculator : IProductionCalculator
    {
        private readonly IProductionRepository _productionRepository;
        private readonly IProgramProductionSummaryRepository _summaryRepository;

        public ProductionCalculator(
            IProductionRepository productionRepository,
            IProgramProductionSummaryRepository summaryRepository)
        {
            _productionRepository = productionRepository;
            _summaryRepository = summaryRepository;
        }

        public async Task<int> CalculateProductionAsync(DeviceCurrentStatus current, DeviceCurrentStatus last)
        {
            // 同一程序连续加工
            if (current.NCProgram == last.NCProgram)
            {
                int diff = current.CumulativeCount - last.CumulativeCount;
                return Math.Max(0, await ValidateProductionValueAsync(diff, current)); // 异常值保护，避免负数
            }
            
            // 程序切换逻辑
            return await CalculateProgramSwitchProductionAsync(current, last);
        }

        public async Task<int> CalculateProgramSwitchProductionAsync(DeviceCurrentStatus current, DeviceCurrentStatus last)
        {
            // 检查是否切换到新程序
            if (await IsNewProgramAsync(current.NCProgram, last.NCProgram))
            {
                // 新程序以当前累计数为起点
                return current.CumulativeCount;
            }
            else
            {
                // 切回历史程序，视为重新开始
                return 0;
            }
        }

        public async Task<bool> IsNewProgramAsync(string currentProgram, string lastProgram)
        {
            // 实现程序切换判断逻辑
            return currentProgram != lastProgram && !string.IsNullOrEmpty(currentProgram);
        }

        public async Task HandleCrossDayResetAsync(DeviceCurrentStatus current, DeviceCurrentStatus last)
        {
            // 跨天处理：0点自动重置
            if (current.RecordTime.Date != last.RecordTime.Date)
            {
                // 新日期以首次采集累计值为起点
                // 这个逻辑需要在业务服务中实现
                var todayProduction = await _productionRepository.GetByDeviceAndDateAsync(
                    current.DeviceId, current.RecordTime.Date);
                
                if (!todayProduction.Any())
                {
                    // 如果当天没有生产记录，创建一条记录记录当前累计数
                    var firstRecord = new ProductionRecord
                    {
                        DeviceId = current.DeviceId,
                        NCProgram = current.NCProgram,
                        ProductionDate = current.RecordTime.Date,
                        Quantity = 0,
                        QualityRate = 100,
                        CreatedAt = DateTime.Now
                    };
                    
                    await _productionRepository.AddAsync(firstRecord);
                    await _productionRepository.SaveAsync();
                }
            }
        }

        public async Task<int> ValidateProductionValueAsync(int quantity, DeviceCurrentStatus current)
        {
            // 跳变检测：产量变化超过阈值时跳过
            const int maxJumpThreshold = 1000; // 单次最大产量变化
            
            if (quantity > maxJumpThreshold)
            {
                await LogWarningAsync($"Production jump detected: {quantity} exceeds threshold {maxJumpThreshold}");
                return 0;
            }

            // 负数保护：产量为负数时归零
            if (quantity < 0)
            {
                await LogWarningAsync("Negative production quantity detected, setting to 0");
                return 0;
            }

            return quantity;
        }

        public async Task<ProductionRecord> CreateProductionRecordAsync(int deviceId, DeviceCurrentStatus current, DeviceCurrentStatus last, int quantity)
        {
            var productionRecord = new ProductionRecord
            {
                DeviceId = deviceId,
                NCProgram = current.NCProgram,
                ProductionDate = current.RecordTime.Date,
                Quantity = quantity,
                QualityRate = 100, // 默认合格率，可以根据实际情况调整
                StartTime = last != null ? last.RecordTime : (DateTime?)null,
                EndTime = current.RecordTime,
                CreatedAt = DateTime.Now
            };

            await _productionRepository.AddAsync(productionRecord);
            await _productionRepository.SaveAsync();

            // 更新程序产量汇总
            await _summaryRepository.UpdateSummaryAsync(
                deviceId, 
                current.NCProgram, 
                current.RecordTime.Date, 
                quantity, 
                productionRecord.QualityRate);

            return productionRecord;
        }

        private async Task LogWarningAsync(string message)
        {
            // 这里可以实现日志记录逻辑
            Console.WriteLine($"Warning: {message}");
        }
    }

    public class ProductionService : IProductionService
    {
        private readonly IProductionRepository _productionRepository;
        private readonly IProgramProductionSummaryRepository _summaryRepository;
        private readonly IDeviceRepository _deviceRepository;
        private readonly IProductionCalculator _calculator;
        private readonly IProductionScheduler _scheduler;
        private readonly ICollectionResultRepository _collectionRepository;
        private readonly ILoggerService _logger;

        public ProductionService(
            IProductionRepository productionRepository,
            IProgramProductionSummaryRepository summaryRepository,
            IDeviceRepository deviceRepository,
            IProductionCalculator calculator,
            IProductionScheduler scheduler,
            ICollectionResultRepository collectionRepository,
            ILoggerService logger)
        {
            _productionRepository = productionRepository;
            _summaryRepository = summaryRepository;
            _deviceRepository = deviceRepository;
            _calculator = calculator;
            _scheduler = scheduler;
            _collectionRepository = collectionRepository;
            _logger = logger;
        }

        public async Task CalculateProductionAsync(int deviceId)
        {
            try
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null || !device.IsAvailable)
                    return;

                var collectionResults = await _collectionRepository.GetResultsByDeviceIdAsync(deviceId)
                    .OrderBy(cr => cr.CollectionTime)
                    .ToListAsync();

                for (int i = 1; i < collectionResults.Count; i++)
                {
                    var current = collectionResults[i];
                    var last = collectionResults[i - 1];

                    if (current.IsSuccess && last.IsSuccess)
                    {
                        var currentStatus = ParseCollectionResult(current);
                        var lastStatus = ParseCollectionResult(last);

                        if (currentStatus != null && lastStatus != null)
                        {
                            // 处理跨天重置
                            await _calculator.HandleCrossDayResetAsync(currentStatus, lastStatus);

                            // 计算产量
                            var quantity = await _calculator.CalculateProductionAsync(currentStatus, lastStatus);
                            
                            if (quantity > 0)
                            {
                                // 创建生产记录
                                var productionRecord = await _calculator.CreateProductionRecordAsync(
                                    deviceId, currentStatus, lastStatus, quantity);

                                await _logger.LogInformationAsync(
                                    $"Production calculated: Device {device.DeviceCode}, " +
                                    $"Program {currentStatus.NCProgram}, Quantity {quantity}");
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                await _logger.LogErrorAsync(
                    $"Failed to calculate production for device {deviceId}: {ex.Message}");
                throw;
            }
        }

        public async Task CalculateAllProductionAsync()
        {
            var devices = await _deviceRepository.GetAvailableDevicesAsync();
            
            foreach (var device in devices)
            {
                try
                {
                    await CalculateProductionAsync(device.Id);
                }
                catch (Exception ex)
                {
                    await _logger.LogErrorAsync(
                        $"Failed to calculate production for device {device.DeviceCode}: {ex.Message}");
                }
            }
        }

        public async Task<ProductionRecord> GetTodayProductionAsync(int deviceId)
        {
            var today = DateTime.Today;
            var productions = await _productionRepository.GetByDeviceAndDateAsync(deviceId, today);
            
            return productions.OrderByDescending(p => p.CreatedAt).FirstOrDefault();
        }

        public async Task<IEnumerable<ProductionRecord>> GetProductionByDateAsync(int deviceId, DateTime date)
        {
            return await _productionRepository.GetByDeviceAndDateAsync(deviceId, date);
        }

        public async Task<ProductionStatistics> GetProductionStatisticsAsync(int deviceId, DateTime date)
        {
            var productions = await _productionRepository.GetByDeviceAndDateAsync(deviceId, date);
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            
            if (!productions.Any())
            {
                return new ProductionStatistics
                {
                    Date = date,
                    DeviceId = deviceId,
                    DeviceName = device?.DeviceName ?? "",
                    TotalQuantity = 0,
                    ValidQuantity = 0,
                    InvalidQuantity = 0,
                    QualityRate = 100
                };
            }

            var totalQuantity = productions.Sum(p => p.Quantity);
            var qualityRate = productions.Any() ? 
                productions.Average(p => p.QualityRate) : 100;

            return new ProductionStatistics
            {
                Date = date,
                DeviceId = deviceId,
                DeviceName = device?.DeviceName ?? "",
                TotalQuantity = totalQuantity,
                ValidQuantity = (int)(totalQuantity * qualityRate / 100),
                InvalidQuantity = totalQuantity - (int)(totalQuantity * qualityRate / 100),
                QualityRate = qualityRate
            };
        }

        public async Task<ProductionSummary> GetProductionSummaryAsync(DateTime date)
        {
            var devices = await _deviceRepository.GetAllAsync();
            var summaries = new List<ProductionStatistics>();

            foreach (var device in devices)
            {
                var stats = await GetProductionStatisticsAsync(device.Id, date);
                summaries.Add(stats);
            }

            var totalQuantity = summaries.Sum(s => s.TotalQuantity);
            var totalValidQuantity = summaries.Sum(s => s.ValidQuantity);
            var overallQualityRate = totalQuantity > 0 ? 
                (decimal)totalValidQuantity / totalQuantity * 100 : 100;

            return new ProductionSummary
            {
                Date = date,
                DeviceCount = summaries.Count,
                TotalQuantity = totalQuantity,
                TotalValidQuantity = totalValidQuantity,
                TotalInvalidQuantity = totalQuantity - totalValidQuantity,
                OverallQualityRate = overallQualityRate,
                DeviceStatistics = summaries
            };
        }

        public async Task<decimal> GetQualityRateAsync(int deviceId, DateTime date)
        {
            return await _productionRepository.GetQualityRateAsync(deviceId, date);
        }

        public async Task<bool> HasProductionDataAsync(int deviceId, DateTime date)
        {
            return await _productionRepository.HasProductionDataAsync(deviceId, date);
        }

        public async Task ArchiveProductionDataAsync(int daysToKeep = 90)
        {
            var cutoffDate = DateTime.Now.AddDays(-daysToKeep);
            var oldProductions = await _productionRepository.FindAsync(
                p => p.CreatedAt < cutoffDate);

            if (oldProductions.Any())
            {
                await _productionRepository.RemoveRange(oldProductions);
                await _productionRepository.SaveAsync();

                await _logger.LogInformationAsync(
                    $"Archived {oldProductions.Count()} production records older than {daysToKeep} days");
            }
        }

        private DeviceCurrentStatus ParseCollectionResult(CollectionResult result)
        {
            // 这里需要根据实际的CollectionResult结构来解析
            // 暂时返回一个空的实现
            return new DeviceCurrentStatus
            {
                DeviceId = result.DeviceId,
                RecordTime = result.CollectionTime,
                NCProgram = "",
                CumulativeCount = 0
            };
        }
    }

    public class ProductionScheduler : IProductionScheduler
    {
        private readonly IProductionService _productionService;
        private readonly ILoggerService _logger;
        private Timer _calculationTimer;
        private bool _isRunning;

        public ProductionScheduler(
            IProductionService productionService,
            ILoggerService logger)
        {
            _productionService = productionService;
            _logger = logger;
        }

        public async Task StartProductionCalculationAsync()
        {
            if (_isRunning)
                return;

            _isRunning = true;
            
            // 立即执行一次计算
            await _productionService.CalculateAllProductionAsync();

            // 设置定时器，每5分钟执行一次
            _calculationTimer = new Timer(async _ =>
            {
                try
                {
                    await _productionService.CalculateAllProductionAsync();
                    await _logger.LogInformationAsync("Scheduled production calculation completed");
                }
                catch (Exception ex)
                {
                    await _logger.LogErrorAsync($"Scheduled production calculation failed: {ex.Message}");
                }
            }, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

            await _logger.LogInformationAsync("Production calculation scheduler started");
        }

        public async Task StopProductionCalculationAsync()
        {
            if (!_isRunning)
                return;

            _isRunning = false;
            _calculationTimer?.Dispose();
            _calculationTimer = null;

            await _logger.LogInformationAsync("Production calculation scheduler stopped");
        }

        public async Task ScheduleProductionCalculationAsync(int deviceId)
        {
            if (!_isRunning)
            {
                await _logger.LogWarningAsync("Production calculation scheduler is not running");
                return;
            }

            await _productionService.CalculateProductionAsync(deviceId);
        }

        public async Task<DateTime> GetNextCalculationTimeAsync()
        {
            if (!_isRunning || _calculationTimer == null)
                return DateTime.MinValue;

            // 这里可以根据定时器的配置返回下一个执行时间
            return DateTime.Now.AddMinutes(5);
        }

        public async Task<bool> IsCalculationRunningAsync()
        {
            return _isRunning;
        }
    }

    public class ProductionSummary
    {
        public DateTime Date { get; set; }
        public int DeviceCount { get; set; }
        public int TotalQuantity { get; set; }
        public int TotalValidQuantity { get; set; }
        public int TotalInvalidQuantity { get; set; }
        public decimal OverallQualityRate { get; set; }
        public List<ProductionStatistics> DeviceStatistics { get; set; }
    }

    public interface ILoggerService
    {
        Task LogInformationAsync(string message);
        Task LogWarningAsync(string message);
        Task LogErrorAsync(string message);
        Task LogDebugAsync(string message);
    }
}