using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Haoliang.Core.Services; using Haoliang.Models.Models.System; using Haoliang.Models.Models.Production; using Haoliang.Models.Common; namespace Haoliang.Api.Controllers { [Route("api/v1/statistics")] [ApiController] public class StatisticsController : ControllerBase { private readonly IProductionStatisticsService _statisticsService; public StatisticsController(IProductionStatisticsService statisticsService) { _statisticsService = statisticsService; } /// /// Calculate production trends for a specific device and time range /// [HttpGet("production-trends")] public async Task>> GetProductionTrends( [FromQuery] int deviceId, [FromQuery] DateTime startDate, [FromQuery] DateTime endDate) { try { if (deviceId <= 0) return BadRequest(ApiResponse.BadRequest("Invalid device ID")); if (startDate >= endDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var result = await _statisticsService.CalculateProductionTrendsAsync(deviceId, startDate, endDate); return Ok(ApiResponse.Success(result)); } catch (KeyNotFoundException ex) { return NotFound(ApiResponse.NotFound(ex.Message)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error calculating production trends: {ex.Message}")); } } /// /// Generate comprehensive production report /// [HttpGet("production-report")] public async Task>> GetProductionReport([FromQuery] ReportFilter filter) { try { if (filter.StartDate >= filter.EndDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var result = await _statisticsService.GenerateProductionReportAsync(filter); return Ok(ApiResponse.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error generating production report: {ex.Message}")); } } /// /// Calculate efficiency metrics for devices or programs /// [HttpGet("efficiency")] public async Task>> GetEfficiencyMetrics([FromQuery] EfficiencyFilter filter) { try { if (filter.StartDate >= filter.EndDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var result = await _statisticsService.CalculateEfficiencyMetricsAsync(filter); return Ok(ApiResponse.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error calculating efficiency metrics: {ex.Message}")); } } /// /// Perform quality analysis based on production data /// [HttpGet("quality")] public async Task>> GetQualityAnalysis([FromQuery] QualityFilter filter) { try { if (filter.StartDate >= filter.EndDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var result = await _statisticsService.PerformQualityAnalysisAsync(filter); return Ok(ApiResponse.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error performing quality analysis: {ex.Message}")); } } /// /// Get production summary for dashboard display /// [HttpGet("dashboard-summary")] public async Task>> GetDashboardSummary([FromQuery] DashboardFilter filter) { try { var result = await _statisticsService.GetDashboardSummaryAsync(filter); return Ok(ApiResponse.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error getting dashboard summary: {ex.Message}")); } } /// /// Calculate OEE (Overall Equipment Effectiveness) for a specific device /// [HttpGet("oee")] public async Task>> GetOeeMetrics( [FromQuery] int deviceId, [FromQuery] DateTime date) { try { if (deviceId <= 0) return BadRequest(ApiResponse.BadRequest("Invalid device ID")); var result = await _statisticsService.CalculateOeeAsync(deviceId, date); return Ok(ApiResponse.Success(result)); } catch (KeyNotFoundException ex) { return NotFound(ApiResponse.NotFound(ex.Message)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error calculating OEE metrics: {ex.Message}")); } } /// /// Get production forecasts based on historical data /// [HttpGet("forecast")] public async Task>> GetProductionForecast([FromQuery] ForecastFilter filter) { try { if (filter.DeviceId <= 0) return BadRequest(ApiResponse.BadRequest("Invalid device ID")); if (filter.DaysToForecast <= 0 || filter.DaysToForecast > 365) return BadRequest(ApiResponse.BadRequest("Days to forecast must be between 1 and 365")); var result = await _statisticsService.GenerateProductionForecastAsync(filter); return Ok(ApiResponse.Success(result)); } catch (KeyNotFoundException ex) { return NotFound(ApiResponse.NotFound(ex.Message)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error generating production forecast: {ex.Message}")); } } /// /// Detect production anomalies and outliers /// [HttpGet("anomalies")] public async Task>> DetectProductionAnomalies([FromQuery] AnomalyFilter filter) { try { if (filter.StartDate >= filter.EndDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var result = await _statisticsService.DetectProductionAnomaliesAsync(filter); return Ok(ApiResponse.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error detecting production anomalies: {ex.Message}")); } } /// /// Get available devices for statistics /// [HttpGet("devices")] public async Task>>> GetAvailableDevices([FromQuery] bool activeOnly = true) { try { // This would typically get devices from device service // For now, returning empty list var result = new List(); return Ok(ApiResponse>.Success(result)); } catch (Exception ex) { return StatusCode(500, ApiResponse>.InternalServerError($"Error getting available devices: {ex.Message}")); } } /// /// Get production summary for multiple devices /// [HttpGet("multi-device-summary")] public async Task>> GetMultiDeviceSummary([FromQuery] List deviceIds) { try { var filter = new DashboardFilter { DeviceIds = deviceIds, Date = DateTime.Today, IncludeAlerts = true }; var dashboardSummary = await _statisticsService.GetDashboardSummaryAsync(filter); var multiDeviceSummary = new MultiDeviceSummary { GeneratedAt = dashboardSummary.GeneratedAt, DeviceCount = dashboardSummary.TotalDevices, ActiveDeviceCount = dashboardSummary.ActiveDevices, OfflineDeviceCount = dashboardSummary.OfflineDevices, TotalProductionToday = dashboardSummary.TotalProductionToday, TotalProductionThisWeek = dashboardSummary.TotalProductionThisWeek, TotalProductionThisMonth = dashboardSummary.TotalProductionThisMonth, OverallEfficiency = dashboardSummary.OverallEfficiency, OverallQualityRate = dashboardSummary.QualityRate, DeviceSummaries = dashboardSummary.DeviceSummaries }; return Ok(ApiResponse.Success(multiDeviceSummary)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error getting multi-device summary: {ex.Message}")); } } /// /// Get historical production data for charting /// [HttpGet("historical-data")] public async Task>> GetHistoricalProductionData( [FromQuery] int deviceId, [FromQuery] DateTime startDate, [FromQuery] DateTime endDate, [FromQuery] GroupBy groupBy = GroupBy.Date) { try { if (deviceId <= 0) return BadRequest(ApiResponse.BadRequest("Invalid device ID")); if (startDate >= endDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var filter = new ReportFilter { DeviceIds = new List { deviceId }, StartDate = startDate, EndDate = endDate, GroupBy = groupBy }; var report = await _statisticsService.GenerateProductionReportAsync(filter); var historicalData = new HistoricalProductionData { DeviceId = deviceId, PeriodStart = startDate, PeriodEnd = endDate, GroupBy = groupBy, DataPoints = report.SummaryItems.Select(item => new DataPoint { Timestamp = groupBy == GroupBy.Date ? item.Date : groupBy == GroupBy.Hour ? item.Hour : item.Date, Value = item.Quantity, Target = item.TargetQuantity, Efficiency = item.Efficiency }).ToList() }; return Ok(ApiResponse.Success(historicalData)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error getting historical production data: {ex.Message}")); } } /// /// Get production efficiency trends over time /// [HttpGet("efficiency-trends")] public async Task>> GetEfficiencyTrends( [FromQuery] int deviceId, [FromQuery] DateTime startDate, [FromQuery] DateTime endDate, [FromQuery] EfficiencyMetric metric = EfficiencyMetric.Oee) { try { if (deviceId <= 0) return BadRequest(ApiResponse.BadRequest("Invalid device ID")); if (startDate >= endDate) return BadRequest(ApiResponse.BadRequest("Start date must be before end date")); var filter = new EfficiencyFilter { DeviceIds = new List { deviceId }, StartDate = startDate, EndDate = endDate, Metrics = metric }; var efficiencyMetrics = await _statisticsService.CalculateEfficiencyMetricsAsync(filter); var trendData = new EfficiencyTrendData { DeviceId = deviceId, Metric = metric, PeriodStart = startDate, PeriodEnd = endDate, DataPoints = efficiencyMetrics.HourlyData.Select(point => new EfficiencyDataPoint { Timestamp = point.Hour, Availability = point.Availability, Performance = point.Performance, Quality = point.Quality, Oee = point.Oee }).ToList() }; return Ok(ApiResponse.Success(trendData)); } catch (Exception ex) { return StatusCode(500, ApiResponse.InternalServerError($"Error getting efficiency trends: {ex.Message}")); } } } // Supporting models for API responses public class MultiDeviceSummary { public DateTime GeneratedAt { get; set; } public int DeviceCount { get; set; } public int ActiveDeviceCount { get; set; } public int OfflineDeviceCount { get; set; } public decimal TotalProductionToday { get; set; } public decimal TotalProductionThisWeek { get; set; } public decimal TotalProductionThisMonth { get; set; } public decimal OverallEfficiency { get; set; } public decimal OverallQualityRate { get; set; } public List DeviceSummaries { get; set; } } public class HistoricalProductionData { public int DeviceId { get; set; } public DateTime PeriodStart { get; set; } public DateTime PeriodEnd { get; set; } public GroupBy GroupBy { get; set; } public List DataPoints { get; set; } } public class DataPoint { public DateTime Timestamp { get; set; } public decimal Value { get; set; } public decimal Target { get; set; } public decimal Efficiency { get; set; } } public class EfficiencyTrendData { public int DeviceId { get; set; } public EfficiencyMetric Metric { get; set; } public DateTime PeriodStart { get; set; } public DateTime PeriodEnd { get; set; } public List DataPoints { get; set; } } public class EfficiencyDataPoint { public DateTime Timestamp { get; set; } public decimal Availability { get; set; } public decimal Performance { get; set; } public decimal Quality { get; set; } public decimal Oee { get; set; } } }