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.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.BadRequestResult("Invalid device ID"));
if (startDate >= endDate)
return BadRequest(ApiResponse.BadRequestResult("Start date must be before end date"));
var result = await _statisticsService.CalculateProductionTrendsAsync(deviceId, startDate, endDate);
return Ok(ApiResponse.Ok(result));
}
catch (KeyNotFoundException ex)
{
return NotFound(ApiResponse.NotFound(ex.Message));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Start date must be before end date"));
var result = await _statisticsService.GenerateProductionReportAsync(filter);
return Ok(ApiResponse.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Start date must be before end date"));
var result = await _statisticsService.CalculateEfficiencyMetricsAsync(filter);
return Ok(ApiResponse.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Start date must be before end date"));
var result = await _statisticsService.PerformQualityAnalysisAsync(filter);
return Ok(ApiResponse.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Invalid device ID"));
var result = await _statisticsService.CalculateOeeAsync(deviceId, date);
return Ok(ApiResponse.Ok(result));
}
catch (KeyNotFoundException ex)
{
return NotFound(ApiResponse.NotFoundResult(ex.Message));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Invalid device ID"));
if (filter.DaysToForecast <= 0 || filter.DaysToForecast > 365)
return BadRequest(ApiResponse.BadRequestResult("Days to forecast must be between 1 and 365"));
var result = await _statisticsService.GenerateProductionForecastAsync(filter);
return Ok(ApiResponse.Ok(result));
}
catch (KeyNotFoundException ex)
{
return NotFound(ApiResponse.NotFoundResult(ex.Message));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Start date must be before end date"));
var result = await _statisticsService.DetectProductionAnomaliesAsync(filter);
return Ok(ApiResponse.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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>.Ok(result));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse>.InternalServerErrorResult($"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.Ok(multiDeviceSummary));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Invalid device ID"));
if (startDate >= endDate)
return BadRequest(ApiResponse.BadRequestResult("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.HasValue ? item.Date.AddHours(item.Hour.Value) : item.Date) :
item.Date,
Value = item.Quantity,
Target = item.TargetQuantity,
Efficiency = item.Efficiency
}).ToList()
};
return Ok(ApiResponse.Ok(historicalData));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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.BadRequestResult("Invalid device ID"));
if (startDate >= endDate)
return BadRequest(ApiResponse.BadRequestResult("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.Ok(trendData));
}
catch (Exception ex)
{
return StatusCode(500, ApiResponse.InternalServerErrorResult($"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; }
}
}