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

namespace Haoliang.Core.Services
{
    public class ProductionStatisticsService : IProductionStatisticsService
    {
        private readonly IProductionRepository _productionRepository;
        private readonly IDeviceRepository _deviceRepository;
        private readonly ISystemRepository _systemRepository;
        private readonly IAlarmRepository _alarmRepository;
        private readonly ICollectionRepository _collectionRepository;

        public ProductionStatisticsService(
            IProductionRepository productionRepository,
            IDeviceRepository deviceRepository,
            ISystemRepository systemRepository,
            IAlarmRepository alarmRepository,
            ICollectionRepository collectionRepository)
        {
            _productionRepository = productionRepository;
            _deviceRepository = deviceRepository;
            _systemRepository = systemRepository;
            _alarmRepository = alarmRepository;
            _collectionRepository = collectionRepository;
        }

        public async Task<ProductionTrendAnalysis> CalculateProductionTrendsAsync(int deviceId, DateTime startDate, DateTime endDate)
        {
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            if (device == null)
                throw new KeyNotFoundException($"Device {deviceId} not found");

            var productionRecords = await _productionRepository.GetProductionRecordsByDeviceAndDateRangeAsync(
                deviceId, startDate, endDate);

            var dailyData = new List<DailyProduction>();
            decimal totalProduction = 0;
            decimal sumSquaredDifferences = 0;
            decimal mean = 0;
            int dayCount = 0;

            // Group records by date
            var groupedByDate = productionRecords.GroupBy(r => r.Created.Date);

            foreach (var dateGroup in groupedByDate)
            {
                var date = dateGroup.Key;
                var dayRecords = dateGroup.ToList();
                var dayProduction = dayRecords.Sum(r => r.Quantity);

                // Get target for this date (if available)
                var target = await GetProductionTargetAsync(deviceId, date);

                dailyData.Add(new DailyProduction
                {
                    Date = date,
                    Quantity = dayProduction,
                    Target = target,
                    Efficiency = target > 0 ? (dayProduction / target) * 100 : 0,
                    Records = dayRecords
                });

                totalProduction += dayProduction;
                dayCount++;
            }

            if (dayCount > 0)
            {
                mean = totalProduction / dayCount;
                
                // Calculate variance
                foreach (var day in dailyData)
                {
                    sumSquaredDifferences += (decimal)Math.Pow((double)(day.Quantity - mean), 2);
                }
            }

            decimal productionVariance = dayCount > 0 ? (decimal)Math.Sqrt((double)(sumSquaredDifferences / dayCount)) : 0;
            
            // Calculate trend using linear regression
            var trendCoefficient = CalculateLinearRegressionTrend(dailyData);
            var trendDirection = DetermineTrendDirection(trendCoefficient);

            return new ProductionTrendAnalysis
            {
                DeviceId = deviceId,
                DeviceName = device.Name,
                PeriodStart = startDate,
                PeriodEnd = endDate,
                TotalProduction = totalProduction,
                AverageDailyProduction = mean,
                ProductionVariance = productionVariance,
                TrendCoefficient = trendCoefficient,
                TrendDirection = trendDirection,
                DailyData = dailyData
            };
        }

        public async Task<ProductionReport> GenerateProductionReportAsync(ReportFilter filter)
        {
            var summaryItems = new List<ProductionSummaryItem>();
            var metadata = new ReportMetadata();

            // Get production records based on filter
            var records = await _productionRepository.GetProductionRecordsByFilterAsync(filter);

            // Group by device and program
            var groupedData = records.GroupBy(r => new { r.DeviceId, r.ProgramName });

            foreach (var group in groupedData)
            {
                var deviceId = group.Key.DeviceId;
                var programName = group.Key.ProgramName;
                var device = await _deviceRepository.GetByIdAsync(deviceId);

                var totalQuantity = group.Sum(r => r.Quantity);
                var totalTarget = group.Sum(r => r.TargetQuantity);
                
                // Calculate quality rate
                var qualityRate = await CalculateQualityRateAsync(deviceId, programName, filter.StartDate, filter.EndDate);
                
                // Calculate runtime and downtime
                var runtime = CalculateRuntime(group.ToList());
                var downtime = await CalculateDowntimeAsync(deviceId, filter.StartDate, filter.EndDate);

                summaryItems.Add(new ProductionSummaryItem
                {
                    DeviceId = deviceId,
                    DeviceName = device?.Name ?? "Unknown",
                    ProgramName = programName,
                    Quantity = totalQuantity,
                    TargetQuantity = totalTarget,
                    Efficiency = totalTarget > 0 ? (totalQuantity / totalTarget) * 100 : 0,
                    QualityRate = qualityRate,
                    Runtime = runtime,
                    Downtime = downtime
                });
            }

            metadata = CalculateReportMetadata(summaryItems, filter);

            return new ProductionReport
            {
                ReportDate = DateTime.Now,
                ReportType = filter.ReportType,
                SummaryItems = summaryItems,
                Metadata = metadata
            };
        }

        public async Task<EfficiencyMetrics> CalculateEfficiencyMetricsAsync(EfficiencyFilter filter)
        {
            var deviceIds = filter.DeviceIds?.Any() == true ? filter.DeviceIds : 
                (await _deviceRepository.GetAllActiveDevicesAsync()).Select(d => d.Id).ToList();

            var metrics = new List<EfficiencyMetrics>();
            var hourlyData = new List<HourlyEfficiency>();

            foreach (var deviceId in deviceIds)
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null) continue;

                var efficiencyMetrics = await CalculateDeviceEfficiencyAsync(deviceId, filter);
                metrics.Add(efficiencyMetrics);
                
                // Add hourly data if requested
                if (filter.GroupBy == GroupBy.Hour)
                {
                    hourlyData.AddRange(efficiencyMetrics.HourlyData);
                }
            }

            // Calculate aggregate metrics if multiple devices
            var aggregatedMetrics = AggregateEfficiencyMetrics(metrics);

            return aggregatedMetrics;
        }

        public async Task<QualityAnalysis> PerformQualityAnalysisAsync(QualityFilter filter)
        {
            var deviceIds = filter.DeviceIds?.Any() == true ? filter.DeviceIds : 
                (await _deviceRepository.GetAllActiveDevicesAsync()).Select(d => d.Id).ToList();

            var totalProduced = 0m;
            var totalGood = 0m;
            var qualityMetrics = new List<QualityMetric>();
            var defectAnalysis = new List<DefectAnalysis>();

            foreach (var deviceId in deviceIds)
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null) continue;

                // Get production records
                var records = await _productionRepository.GetProductionRecordsByFilterAsync(new ReportFilter
                {
                    DeviceIds = new List<int> { deviceId },
                    StartDate = filter.StartDate,
                    EndDate = filter.EndDate,
                    ProgramNames = filter.ProgramNames
                });

                var deviceTotalProduced = records.Sum(r => r.Quantity);
                var deviceTotalGood = records.Where(r => r.IsGood).Sum(r => r.Quantity);
                
                totalProduced += deviceTotalProduced;
                totalGood += deviceTotalGood;

                // Calculate quality metrics for this device
                var deviceMetrics = await CalculateDeviceQualityMetricsAsync(deviceId, filter);
                qualityMetrics.AddRange(deviceMetrics);

                // Perform defect analysis
                var deviceDefects = await AnalyzeDefectsAsync(deviceId, filter);
                defectAnalysis.AddRange(deviceDefects);
            }

            var qualityRate = totalProduced > 0 ? (totalGood / totalProduced) * 100 : 0;
            var defectRate = totalProduced > 0 ? 100 - qualityRate : 0;

            return new QualityAnalysis
            {
                DeviceIds = deviceIds,
                DeviceNames = deviceIds.Select(id => _deviceRepository.GetByIdAsync(id).Result?.Name ?? "Unknown").ToList(),
                PeriodStart = filter.StartDate,
                PeriodEnd = filter.EndDate,
                TotalProduced = totalProduced,
                TotalGood = totalGood,
                QualityRate = qualityRate,
                DefectRate = defectRate,
                QualityMetrics = qualityMetrics,
                DefectAnalysis = defectAnalysis
            };
        }

        public async Task<DashboardSummary> GetDashboardSummaryAsync(DashboardFilter filter)
        {
            var deviceIds = filter.DeviceIds?.Any() == true ? filter.DeviceIds : 
                (await _deviceRepository.GetAllDevicesAsync()).Select(d => d.Id).ToList();

            var deviceSummaries = new List<DeviceSummary>();
            var activeAlerts = new List<AlertSummary>();

            int totalDevices = deviceIds.Count;
            int activeDevices = 0;
            int offlineDevices = 0;

            decimal totalProductionToday = 0;
            decimal totalProductionThisWeek = 0;
            decimal totalProductionThisMonth = 0;
            decimal overallEfficiency = 0;
            decimal qualityRate = 0;
            int efficiencyCount = 0;

            foreach (var deviceId in deviceIds)
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null) continue;

                // Get device status
                var deviceStatus = await GetDeviceCurrentStatusAsync(deviceId);
                
                // Get today's production
                var todayProduction = await GetDeviceProductionForDateAsync(deviceId, DateTime.Today);
                
                // Get weekly and monthly production
                var weekStart = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
                var weekProduction = await GetDeviceProductionForDateRangeAsync(deviceId, weekStart, DateTime.Today);
                
                var monthStart = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
                var monthProduction = await GetDeviceProductionForDateRangeAsync(deviceId, monthStart, DateTime.Today);

                // Calculate efficiency and quality
                var efficiency = await CalculateDeviceEfficiencyAsync(deviceId, new EfficiencyFilter
                {
                    DeviceIds = new List<int> { deviceId },
                    StartDate = DateTime.Today,
                    EndDate = DateTime.Today
                });

                var quality = await CalculateQualityRateAsync(deviceId, null, DateTime.Today, DateTime.Today);

                deviceSummaries.Add(new DeviceSummary
                {
                    DeviceId = deviceId,
                    DeviceName = device.Name,
                    Status = deviceStatus.Status,
                    TodayProduction = todayProduction,
                    Efficiency = efficiency.Oee,
                    QualityRate = quality,
                    Runtime = deviceStatus.Runtime,
                    CurrentProgram = deviceStatus.CurrentProgram
                });

                totalProductionToday += todayProduction;
                totalProductionThisWeek += weekProduction;
                totalProductionThisMonth += monthProduction;
                overallEfficiency += efficiency.Oee;
                qualityRate += quality;
                efficiencyCount++;

                // Count devices by status
                if (deviceStatus.Status == DeviceStatus.Online)
                    activeDevices++;
                else
                    offlineDevices++;

                // Get active alerts
                var alerts = await GetDeviceAlertsAsync(deviceId);
                activeAlerts.AddRange(alerts);
            }

            // Calculate averages
            overallEfficiency = efficiencyCount > 0 ? overallEfficiency / efficiencyCount : 0;
            qualityRate = efficiencyCount > 0 ? qualityRate / efficiencyCount : 0;

            return new DashboardSummary
            {
                GeneratedAt = DateTime.Now,
                TotalDevices = totalDevices,
                ActiveDevices = activeDevices,
                OfflineDevices = offlineDevices,
                TotalProductionToday = totalProductionToday,
                TotalProductionThisWeek = totalProductionThisWeek,
                TotalProductionThisMonth = totalProductionThisMonth,
                OverallEfficiency = overallEfficiency,
                QualityRate = qualityRate,
                DeviceSummaries = deviceSummaries,
                ActiveAlerts = activeAlerts
            };
        }

        public async Task<OeeMetrics> CalculateOeeAsync(int deviceId, DateTime date)
        {
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            if (device == null)
                throw new KeyNotFoundException($"Device {deviceId} not found");

            // Get planned production time (typically 8 hours or as configured)
            var plannedProductionTime = await GetPlannedProductionTimeAsync(deviceId, date);
            
            // Get actual production time
            var productionRecords = await _productionRepository.GetProductionRecordsByDeviceAndDateAsync(deviceId, date);
            var actualProductionTime = CalculateProductionTime(productionRecords);
            
            // Calculate downtime
            var downtime = plannedProductionTime - actualProductionTime;
            
            // Get performance metrics
            var totalPieces = productionRecords.Sum(r => r.Quantity);
            var goodPieces = productionRecords.Where(r => r.IsGood).Sum(r => r.Quantity);
            
            // Calculate OEE components
            var availability = CalculateAvailability(plannedProductionTime, actualProductionTime);
            var performance = await CalculatePerformanceAsync(deviceId, date);
            var quality = totalPieces > 0 ? (goodPieces / totalPieces) * 100 : 0;
            var oee = (availability * performance * quality) / 10000; // Convert percentage back to decimal

            return new OeeMetrics
            {
                DeviceId = deviceId,
                DeviceName = device.Name,
                Date = date,
                Availability = availability,
                Performance = performance,
                Quality = quality,
                Oee = oee,
                PlannedProductionTime = plannedProductionTime,
                ActualProductionTime = actualProductionTime,
                Downtime = downtime,
                IdealCycleTime = await GetIdealCycleTimeAsync(deviceId),
                TotalCycleTime = actualProductionTime,
                TotalPieces = totalPieces,
                GoodPieces = goodPieces
            };
        }

        public async Task<ProductionForecast> GenerateProductionForecastAsync(ForecastFilter filter)
        {
            var device = await _deviceRepository.GetByIdAsync(filter.DeviceId);
            if (device == null)
                throw new KeyNotFoundException($"Device {filter.DeviceId} not found");

            var historicalData = await _productionRepository.GetProductionRecordsByDeviceAndDateRangeAsync(
                filter.DeviceId, filter.HistoricalDataStart, filter.HistoricalDataEnd);

            var dailyForecasts = new List<ForecastItem>();
            var forecastAccuracy = 0.0m;

            switch (filter.Model)
            {
                case ForecastModel.Linear:
                    dailyForecasts = GenerateLinearForecast(historicalData, filter.DaysToForecast);
                    break;
                case ForecastModel.ExponentialSmoothing:
                    dailyForecasts = GenerateExponentialSmoothingForecast(historicalData, filter.DaysToForecast);
                    break;
                case ForecastModel.MovingAverage:
                    dailyForecasts = GenerateMovingAverageForecast(historicalData, filter.DaysToForecast);
                    break;
                default:
                    dailyForecasts = GenerateLinearForecast(historicalData, filter.DaysToForecast);
                    break;
            }

            // Calculate forecast accuracy if we have actual data
            forecastAccuracy = CalculateForecastAccuracy(dailyForecasts);

            return new ProductionForecast
            {
                DeviceId = filter.DeviceId,
                DeviceName = device.Name,
                ForecastStartDate = DateTime.Today,
                ForecastEndDate = DateTime.Today.AddDays(filter.DaysToForecast - 1),
                DailyForecasts = dailyForecasts,
                ForecastAccuracy = forecastAccuracy,
                ModelUsed = filter.Model
            };
        }

        public async Task<AnomalyAnalysis> DetectProductionAnomaliesAsync(AnomalyFilter filter)
        {
            var deviceIds = filter.DeviceIds?.Any() == true ? filter.DeviceIds : 
                (await _deviceRepository.GetAllActiveDevicesAsync()).Select(d => d.Id).ToList();

            var anomalies = new List<ProductionAnomaly>();

            foreach (var deviceId in deviceIds)
            {
                var device = await _deviceRepository.GetByIdAsync(deviceId);
                if (device == null) continue;

                var productionRecords = await _productionRepository.GetProductionRecordsByDeviceAndDateRangeAsync(
                    deviceId, filter.StartDate, filter.EndDate);

                // Detect production drop anomalies
                if (!filter.Type.HasValue || filter.Type.Value == AnomalyType.ProductionDrop)
                {
                    var dropAnomalies = DetectProductionDropAnomalies(productionRecords);
                    anomalies.AddRange(dropAnomalies);
                }

                // Detect quality spike anomalies
                if (!filter.Type.HasValue || filter.Type.Value == AnomalyType.QualitySpike)
                {
                    var qualityAnomalies = DetectQualitySpikeAnomalies(productionRecords);
                    anomalies.AddRange(qualityAnomalies);
                }

                // Detect downtime spike anomalies
                if (!filter.Type.HasValue || filter.Type.Value == AnomalyType.DowntimeSpike)
                {
                    var downtimeAnomalies = DetectDowntimeSpikeAnomalies(deviceId, productionRecords);
                    anomalies.AddRange(downtimeAnomalies);
                }

                // Detect efficiency drop anomalies
                if (!filter.Type.HasValue || filter.Type.Value == AnomalyType.EfficiencyDrop)
                {
                    var efficiencyAnomalies = DetectEfficiencyDropAnomalies(productionRecords);
                    anomalies.AddRange(efficiencyAnomalies);
                }
            }

            // Filter by severity
            if (filter.MinSeverity.HasValue)
            {
                anomalies = anomalies.Where(a => a.Severity >= filter.MinSeverity.Value).ToList();
            }

            // Determine overall severity
            var overallSeverity = DetermineOverallAnomalySeverity(anomalies);

            return new AnomalyAnalysis
            {
                DeviceIds = deviceIds,
                DeviceNames = deviceIds.Select(id => _deviceRepository.GetByIdAsync(id).Result?.Name ?? "Unknown").ToList(),
                AnalysisStartDate = filter.StartDate,
                AnalysisEndDate = filter.EndDate,
                Anomalies = anomalies,
                OverallSeverity = overallSeverity
            };
        }

        #region Private Methods

        private decimal CalculateLinearRegressionTrend(List<DailyProduction> dailyData)
        {
            if (dailyData.Count < 2) return 0;

            int n = dailyData.Count;
            decimal sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;

            for (int i = 0; i < n; i++)
            {
                sumX += i;
                sumY += dailyData[i].Quantity;
                sumXY += i * dailyData[i].Quantity;
                sumXX += i * i;
            }

            // Linear regression: y = mx + b, where m is the slope
            decimal numerator = n * sumXY - sumX * sumY;
            decimal denominator = n * sumXX - sumX * sumX;

            return denominator != 0 ? numerator / denominator : 0;
        }

        private ProductionTrendDirection DetermineTrendDirection(decimal trendCoefficient)
        {
            if (trendCoefficient > 0.1m)
                return ProductionTrendDirection.Increasing;
            else if (trendCoefficient < -0.1m)
                return ProductionTrendDirection.Decreasing;
            else if (Math.Abs(trendCoefficient) <= 0.1m && Math.Abs(trendCoefficient) > 0.01m)
                return ProductionTrendDirection.Stable;
            else
                return ProductionTrendDirection.Volatile;
        }

        private async Task<decimal> GetProductionTargetAsync(int deviceId, DateTime date)
        {
            // This would typically come from system configuration or production planning
            var systemConfig = await _systemRepository.GetSystemConfigurationAsync();
            return systemConfig?.DailyProductionTarget ?? 100; // Default target
        }

        private async Task<decimal> CalculateQualityRateAsync(int deviceId, string programName, DateTime startDate, DateTime endDate)
        {
            var records = await _productionRepository.GetProductionRecordsByFilterAsync(new ReportFilter
            {
                DeviceIds = new List<int> { deviceId },
                ProgramNames = programName != null ? new List<string> { programName } : null,
                StartDate = startDate,
                EndDate = endDate
            });

            var totalQuantity = records.Sum(r => r.Quantity);
            var goodQuantity = records.Where(r => r.IsGood).Sum(r => r.Quantity);

            return totalQuantity > 0 ? (goodQuantity / totalQuantity) * 100 : 0;
        }

        private TimeSpan CalculateRuntime(List<ProductionRecord> records)
        {
            if (records == null || records.Count == 0) return TimeSpan.Zero;

            var startTime = records.Min(r => r.Created);
            var endTime = records.Max(r => r.Created);
            return endTime - startTime;
        }

        private async Task<TimeSpan> CalculateDowntimeAsync(int deviceId, DateTime startDate, DateTime endDate)
        {
            // Get device status changes
            var statusRecords = await _collectionRepository.GetDeviceStatusHistoryAsync(deviceId, startDate, endDate);
            
            // Calculate total downtime (time when device was not in production state)
            var downtime = TimeSpan.Zero;
            var previousTime = startDate;

            foreach (var status in statusRecords.OrderBy(s => s.Timestamp))
            {
                if (status.Status != DeviceStatus.Running && status.Status != DeviceStatus.Idle)
                {
                    downtime += status.Timestamp - previousTime;
                }
                previousTime = status.Timestamp;
            }

            // Add remaining time
            downtime += endDate - previousTime;

            return downtime;
        }

        private ReportMetadata CalculateReportMetadata(List<ProductionSummaryItem> summaryItems, ReportFilter filter)
        {
            return ReportMetadata.GeneratedAt; // Simplified for now
        }

        private async Task<EfficiencyMetrics> CalculateDeviceEfficiencyAsync(int deviceId, EfficiencyFilter filter)
        {
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            if (device == null)
                throw new KeyNotFoundException($"Device {deviceId} not found");

            var records = await _productionRepository.GetProductionRecordsByDeviceAndDateRangeAsync(
                deviceId, filter.StartDate, filter.EndDate);

            var hourlyData = new List<HourlyEfficiency>();
            var totalAvailability = 0m;
            var totalPerformance = 0m;
            var totalQuality = 0m;
            var hourCount = 0;

            // Group by hour if requested
            if (filter.GroupBy == GroupBy.Hour)
            {
                var groupedByHour = records.GroupBy(r => r.Created.Date.AddHours(r.Created.Hour));

                foreach (var hourGroup in groupedByHour)
                {
                    var hour = hourGroup.Key;
                    var hourRecords = hourGroup.ToList();

                    // Calculate efficiency metrics for this hour
                    var availability = await CalculateHourlyAvailabilityAsync(deviceId, hour);
                    var performance = await CalculateHourlyPerformanceAsync(deviceId, hour);
                    var quality = CalculateHourlyQuality(hourRecords);

                    hourlyData.Add(new HourlyEfficiency
                    {
                        Hour = hour,
                        Availability = availability,
                        Performance = performance,
                        Quality = quality,
                        Oee = (availability * performance * quality) / 100
                    });

                    totalAvailability += availability;
                    totalPerformance += performance;
                    totalQuality += quality;
                    hourCount++;
                }
            }

            // Calculate overall metrics
            var availability = hourCount > 0 ? totalAvailability / hourCount : 0;
            var performance = hourCount > 0 ? totalPerformance / hourCount : 0;
            var quality = hourCount > 0 ? totalQuality / hourCount : 0;
            var oee = (availability * performance * quality) / 100;

            return new EfficiencyMetrics
            {
                DeviceId = deviceId,
                DeviceName = device.Name,
                PeriodStart = filter.StartDate,
                PeriodEnd = filter.EndDate,
                Availability = availability,
                Performance = performance,
                Quality = quality,
                Oee = oee,
                Utilization = DetermineUtilizationLevel(oee),
                HourlyData = hourlyData
            };
        }

        private EfficiencyMetrics AggregateEfficiencyMetrics(List<EfficiencyMetrics> metrics)
        {
            if (metrics == null || metrics.Count == 0)
                return new EfficiencyMetrics();

            var aggregated = new EfficiencyMetrics
            {
                DeviceIds = metrics.Select(m => m.DeviceId).ToList(),
                PeriodStart = metrics.Min(m => m.PeriodStart),
                PeriodEnd = metrics.Max(m => m.PeriodEnd),
                Availability = metrics.Average(m => m.Availability),
                Performance = metrics.Average(m => m.Performance),
                Quality = metrics.Average(m => m.Quality),
                Oee = metrics.Average(m => m.Oee),
                HourlyData = metrics.SelectMany(m => m.HourlyData).ToList()
            };

            aggregated.Utilization = DetermineUtilizationLevel(aggregated.Oee);
            return aggregated;
        }

        private EquipmentUtilization DetermineUtilizationLevel(decimal oee)
        {
            if (oee >= 85) return EquipmentUtilization.Optimal;
            if (oee >= 70) return EquipmentUtilization.High;
            if (oee >= 50) return EquipmentUtilization.Medium;
            return EquipmentUtilization.Low;
        }

        private async Task<List<QualityMetric>> CalculateDeviceQualityMetricsAsync(int deviceId, QualityFilter filter)
        {
            // Simplified quality metrics calculation
            var metrics = new List<QualityMetric>();
            
            var defectRate = await CalculateQualityRateAsync(deviceId, null, filter.StartDate, filter.EndDate);
            metrics.Add(new QualityMetric
            {
                MetricName = "Defect Rate",
                Value = 100 - defectRate,
                Unit = "%",
                Timestamp = DateTime.Now
            });

            return metrics;
        }

        private async Task<List<DefectAnalysis>> AnalyzeDefectsAsync(int deviceId, QualityFilter filter)
        {
            // Simplified defect analysis
            return new List<DefectAnalysis>();
        }

        private async Task<DeviceCurrentStatus> GetDeviceCurrentStatusAsync(int deviceId)
        {
            // This would typically get current status from real-time data
            var records = await _collectionRepository.GetLatestDeviceStatusAsync(deviceId);
            return records ?? new DeviceCurrentStatus();
        }

        private async Task<decimal> GetDeviceProductionForDateAsync(int deviceId, DateTime date)
        {
            var records = await _productionRepository.GetProductionRecordsByDeviceAndDateAsync(deviceId, date);
            return records.Sum(r => r.Quantity);
        }

        private async Task<decimal> GetDeviceProductionForDateRangeAsync(int deviceId, DateTime startDate, DateTime endDate)
        {
            var records = await _productionRepository.GetProductionRecordsByDeviceAndDateRangeAsync(deviceId, startDate, endDate);
            return records.Sum(r => r.Quantity);
        }

        private async Task<List<AlertSummary>> GetDeviceAlertsAsync(int deviceId)
        {
            var alerts = await _alarmRepository.GetActiveAlertsByDeviceAsync(deviceId);
            return alerts.Select(a => new AlertSummary
            {
                AlertId = a.Id,
                DeviceName = "Device " + deviceId, // Simplified
                AlertType = (AlertType)a.AlertType,
                Message = a.Message,
                CreatedAt = a.CreatedAt,
                IsActive = a.IsActive
            }).ToList();
        }

        private async Task<TimeSpan> GetPlannedProductionTimeAsync(int deviceId, DateTime date)
        {
            // This would typically come from system configuration
            var systemConfig = await _systemRepository.GetSystemConfigurationAsync();
            return systemConfig?.DailyWorkingHours ?? TimeSpan.FromHours(8);
        }

        private TimeSpan CalculateProductionTime(List<ProductionRecord> records)
        {
            if (records == null || records.Count == 0) return TimeSpan.Zero;

            var startTime = records.Min(r => r.Created);
            var endTime = records.Max(r => r.Created);
            return endTime - startTime;
        }

        private decimal CalculateAvailability(TimeSpan plannedTime, TimeSpan actualTime)
        {
            return plannedTime.TotalMinutes > 0 ? 
                (actualTime.TotalMinutes / plannedTime.TotalMinutes) * 100 : 0;
        }

        private async Task<decimal> CalculatePerformanceAsync(int deviceId, DateTime date)
        {
            // Simplified performance calculation
            var records = await _productionRepository.GetProductionRecordsByDeviceAndDateAsync(deviceId, date);
            var totalPieces = records.Sum(r => r.Quantity);
            
            var idealCycleTime = await GetIdealCycleTimeAsync(deviceId);
            var standardPieces = idealCycleTime > 0 ? (24 * 60) / idealCycleTime : 0; // Assuming 24 hours operation
            
            return standardPieces > 0 ? (totalPieces / standardPieces) * 100 : 0;
        }

        private async Task<decimal> GetIdealCycleTimeAsync(int deviceId)
        {
            // This would typically come from device configuration
            var device = await _deviceRepository.GetByIdAsync(deviceId);
            return device?.IdealCycleTime ?? 1; // Default 1 minute per piece
        }

        private decimal CalculateHourlyQuality(List<ProductionRecord> hourRecords)
        {
            if (hourRecords == null || hourRecords.Count == 0) return 0;

            var totalQuantity = hourRecords.Sum(r => r.Quantity);
            var goodQuantity = hourRecords.Where(r => r.IsGood).Sum(r => r.Quantity);

            return totalQuantity > 0 ? (goodQuantity / totalQuantity) * 100 : 0;
        }

        private async Task<decimal> CalculateHourlyAvailabilityAsync(int deviceId, DateTime hour)
        {
            // Simplified availability calculation
            return 85m; // Default 85% availability
        }

        private async Task<decimal> CalculateHourlyPerformanceAsync(int deviceId, DateTime hour)
        {
            // Simplified performance calculation
            return 90m; // Default 90% performance
        }

        private List<ForecastItem> GenerateLinearForecast(List<ProductionRecord> historicalData, int daysToForecast)
        {
            var forecasts = new List<ForecastItem>();
            var lastDate = historicalData.Max(r => r.Created);
            
            // Calculate average daily production
            var avgDailyProduction = historicalData.Average(r => r.Quantity);
            
            for (int i = 1; i <= daysToForecast; i++)
            {
                var forecastDate = lastDate.AddDays(i);
                var forecastQuantity = avgDailyProduction; // Simple average
                
                forecasts.Add(new ForecastItem
                {
                    Date = forecastDate,
                    ForecastedQuantity = forecastQuantity,
                    ConfidenceLower = forecastQuantity * 0.8m,
                    ConfidenceUpper = forecastQuantity * 1.2m,
                    ActualQuantity = 0, // Will be updated when actual data is available
                    Variance = 0
                });
            }
            
            return forecasts;
        }

        private List<ForecastItem> GenerateExponentialSmoothingForecast(List<ProductionRecord> historicalData, int daysToForecast)
        {
            // Simplified exponential smoothing
            var alpha = 0.3m; // Smoothing factor
            var forecasts = new List<ForecastItem>();
            
            if (historicalData.Count == 0) return forecasts;
            
            var lastSmoothed = historicalData.First().Quantity;
            var lastDate = historicalData.Max(r => r.Created);
            
            for (int i = 1; i <= daysToForecast; i++)
            {
                var forecastDate = lastDate.AddDays(i);
                var forecastQuantity = lastSmoothed;
                
                forecasts.Add(new ForecastItem
                {
                    Date = forecastDate,
                    ForecastedQuantity = forecastQuantity,
                    ConfidenceLower = forecastQuantity * 0.85m,
                    ConfidenceUpper = forecastQuantity * 1.15m,
                    ActualQuantity = 0,
                    Variance = 0
                });
                
                lastSmoothed = alpha * forecastQuantity + (1 - alpha) * lastSmoothed;
            }
            
            return forecasts;
        }

        private List<ForecastItem> GenerateMovingAverageForecast(List<ProductionRecord> historicalData, int daysToForecast)
        {
            var forecasts = new List<ForecastItem>();
            var windowSize = Math.Min(7, historicalData.Count); // 7-day moving average
            
            if (historicalData.Count < windowSize) return forecasts;
            
            var lastDate = historicalData.Max(r => r.Created);
            
            // Calculate moving average
            var movingAvg = historicalData.TakeLast(windowSize).Average(r => r.Quantity);
            
            for (int i = 1; i <= daysToForecast; i++)
            {
                var forecastDate = lastDate.AddDays(i);
                var forecastQuantity = movingAvg;
                
                forecasts.Add(new ForecastItem
                {
                    Date = forecastDate,
                    ForecastedQuantity = forecastQuantity,
                    ConfidenceLower = forecastQuantity * 0.9m,
                    ConfidenceUpper = forecastQuantity * 1.1m,
                    ActualQuantity = 0,
                    Variance = 0
                });
            }
            
            return forecasts;
        }

        private decimal CalculateForecastAccuracy(List<ForecastItem> forecasts)
        {
            // Simplified accuracy calculation based on confidence intervals
            var accurateForecasts = forecasts.Count(f => f.ForecastedQuantity >= f.ConfidenceLower && 
                                                      f.ForecastedQuantity <= f.ConfidenceUpper);
            return forecasts.Count > 0 ? (accurateForecasts / forecasts.Count) * 100 : 0;
        }

        private List<ProductionAnomaly> DetectProductionDropAnomalies(List<ProductionRecord> records)
        {
            var anomalies = new List<ProductionAnomaly>();
            
            if (records.Count < 2) return anomalies;
            
            // Compare each day with the previous day
            var groupedByDay = records.GroupBy(r => r.Created.Date).OrderBy(g => g.Key);
            
            var previousDay = groupedByDay.FirstOrDefault();
            foreach (var currentDay in groupedByDay.Skip(1))
            {
                var previousQuantity = previousDay.Sum(r => r.Quantity);
                var currentQuantity = currentDay.Sum(r => r.Quantity);
                
                if (previousQuantity > 0)
                {
                    var dropPercentage = (decimal)((previousQuantity - currentQuantity) / (double)previousQuantity * 100);
                    
                    if (dropPercentage > 30) // 30% drop threshold
                    {
                        anomalies.Add(new ProductionAnomaly
                        {
                            Timestamp = currentDay.Key,
                            Type = AnomalyType.ProductionDrop,
                            Severity = dropPercentage > 50 ? AnomalySeverity.Critical : AnomalySeverity.High,
                            Deviation = dropPercentage,
                            Description = $"Production dropped by {dropPercentage:F1}% from previous day",
                            RecommendedAction = dropPercentage > 50 ? AnomalyAction.Shutdown : AnomalyAction.Investigate
                        });
                    }
                }
                
                previousDay = currentDay;
            }
            
            return anomalies;
        }

        private List<ProductionAnomaly> DetectQualitySpikeAnomalies(List<ProductionRecord> records)
        {
            var anomalies = new List<ProductionAnomaly>();
            
            if (records.Count == 0) return anomalies;
            
            var qualityRates = records.GroupBy(r => r.Created.Date)
                .Select(g => new
                {
                    Date = g.Key,
                    QualityRate = g.Where(r => r.IsGood).Average(r => (decimal)r.Quantity / (decimal)g.Sum(r => r.Quantity)) * 100
                });
            
            var avgQuality = qualityRates.Average(q => q.QualityRate);
            
            foreach (var day in qualityRates)
            {
                var deviation = Math.Abs((decimal)(day.QualityRate - avgQuality));
                
                if (deviation > 20 && day.QualityRate > avgQuality) // Significant quality improvement
                {
                    anomalies.Add(new ProductionAnomaly
                    {
                        Timestamp = day.Date,
                        Type = AnomalyType.QualitySpike,
                        Severity = deviation > 30 ? AnomalySeverity.High : AnomalySeverity.Medium,
                        Deviation = deviation,
                        Description = $"Quality rate spiked to {day.QualityRate:F1}%",
                        RecommendedAction = AnomalyAction.Monitor
                    });
                }
            }
            
            return anomalies;
        }

        private List<ProductionAnomaly> DetectDowntimeSpikeAnomalies(int deviceId, List<ProductionRecord> records)
        {
            var anomalies = new List<ProductionAnomaly>();
            
            // Simplified downtime spike detection
            var downtimePeriods = CalculateDowntimePeriods(records);
            
            var avgDowntime = downtimePeriods.Average(d => d.Duration.TotalMinutes);
            
            foreach (var period in downtimePeriods)
            {
                if (period.Duration.TotalMinutes > avgDowntime * 2) // Double the average downtime
                {
                    anomalies.Add(new ProductionAnomaly
                    {
                        Timestamp = period.Start,
                        Type = AnomalyType.DowntimeSpike,
                        Severity = period.Duration.TotalMinutes > 120 ? AnomalySeverity.Critical : AnomalySeverity.High,
                        Deviation = (decimal)(period.Duration.TotalMinutes / avgDowntime),
                        Description = $"Extended downtime period: {period.Duration.TotalMinutes:F0} minutes",
                        RecommendedAction = period.Duration.TotalMinutes > 120 ? AnomalyAction.Shutdown : AnomalyAction.Alert
                    });
                }
            }
            
            return anomalies;
        }

        private List<ProductionAnomaly> DetectEfficiencyDropAnomalies(List<ProductionRecord> records)
        {
            var anomalies = new List<ProductionAnomaly>();
            
            // Simplified efficiency drop detection
            var efficiencies = records.GroupBy(r => r.Created.Date)
                .Select(g => new
                {
                    Date = g.Key,
                    Efficiency = g.Sum(r => r.Quantity) / g.Sum(r => r.TargetQuantity) * 100
                });
            
            var avgEfficiency = efficiencies.Average(e => e.Efficiency);
            
            foreach (var day in efficiencies)
            {
                if (day.Efficiency < avgEfficiency * 0.7) // 30% below average
                {
                    anomalies.Add(new ProductionAnomaly
                    {
                        Timestamp = day.Date,
                        Type = AnomalyType.EfficiencyDrop,
                        Severity = day.Efficiency < avgEfficiency * 0.5 ? AnomalySeverity.Critical : AnomalySeverity.High,
                        Deviation = avgEfficiency - day.Efficiency,
                        Description = $"Efficiency dropped to {day.Efficiency:F1}%",
                        RecommendedAction = AnomalyAction.Investigate
                    });
                }
            }
            
            return anomalies;
        }

        private List<DowntimePeriod> CalculateDowntimePeriods(List<ProductionRecord> records)
        {
            var downtimePeriods = new List<DowntimePeriod>();
            
            if (records.Count == 0) return downtimePeriods;
            
            var sortedRecords = records.OrderBy(r => r.Created).ToList();
            var downtimeStart = sortedRecords.First().Created;
            
            foreach (var record in sortedRecords)
            {
                // Assume there's downtime if there's a gap of more than 5 minutes between records
                if (record.Created - downtimeStart > TimeSpan.FromMinutes(5))
                {
                    downtimePeriods.Add(new DowntimePeriod
                    {
                        Start = downtimeStart,
                        End = record.Created,
                        Duration = record.Created - downtimeStart
                    });
                    
                    downtimeStart = record.Created;
                }
            }
            
            return downtimePeriods;
        }

        private AnomalySeverity DetermineOverallAnomalySeverity(List<ProductionAnomaly> anomalies)
        {
            if (anomalies.Count == 0) return AnomalySeverity.Low;
            
            var maxSeverity = anomalies.Max(a => a.Severity);
            var criticalCount = anomalies.Count(a => a.Severity == AnomalySeverity.Critical);
            
            if (criticalCount > 0) return AnomalySeverity.Critical;
            if (maxSeverity >= AnomalySeverity.High) return AnomalySeverity.High;
            if (maxSeverity >= AnomalySeverity.Medium) return AnomalySeverity.Medium;
            
            return AnomalySeverity.Low;
        }

        #endregion
    }

    // Helper class for downtime periods
    internal class DowntimePeriod
    {
        public DateTime Start { get; set; }
        public DateTime End { get; set; }
        public TimeSpan Duration { get; set; }
    }
}