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;
        }

        /// <summary>
        /// Calculate production trends for a specific device and time range
        /// </summary>
        [HttpGet("production-trends")]
        public async Task<ActionResult<ApiResponse<ProductionTrendAnalysis>>> GetProductionTrends(
            [FromQuery] int deviceId,
            [FromQuery] DateTime startDate,
            [FromQuery] DateTime endDate)
        {
            try
            {
                if (deviceId <= 0)
                    return BadRequest(ApiResponse<ProductionTrendAnalysis>.BadRequest("Invalid device ID"));

                if (startDate >= endDate)
                    return BadRequest(ApiResponse<ProductionTrendAnalysis>.BadRequest("Start date must be before end date"));

                var result = await _statisticsService.CalculateProductionTrendsAsync(deviceId, startDate, endDate);
                
                return Ok(ApiResponse<ProductionTrendAnalysis>.Success(result));
            }
            catch (KeyNotFoundException ex)
            {
                return NotFound(ApiResponse<ProductionTrendAnalysis>.NotFound(ex.Message));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<ProductionTrendAnalysis>.InternalServerError($"Error calculating production trends: {ex.Message}"));
            }
        }

        /// <summary>
        /// Generate comprehensive production report
        /// </summary>
        [HttpGet("production-report")]
        public async Task<ActionResult<ApiResponse<ProductionReport>>> GetProductionReport([FromQuery] ReportFilter filter)
        {
            try
            {
                if (filter.StartDate >= filter.EndDate)
                    return BadRequest(ApiResponse<ProductionReport>.BadRequest("Start date must be before end date"));

                var result = await _statisticsService.GenerateProductionReportAsync(filter);
                
                return Ok(ApiResponse<ProductionReport>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<ProductionReport>.InternalServerError($"Error generating production report: {ex.Message}"));
            }
        }

        /// <summary>
        /// Calculate efficiency metrics for devices or programs
        /// </summary>
        [HttpGet("efficiency")]
        public async Task<ActionResult<ApiResponse<EfficiencyMetrics>>> GetEfficiencyMetrics([FromQuery] EfficiencyFilter filter)
        {
            try
            {
                if (filter.StartDate >= filter.EndDate)
                    return BadRequest(ApiResponse<EfficiencyMetrics>.BadRequest("Start date must be before end date"));

                var result = await _statisticsService.CalculateEfficiencyMetricsAsync(filter);
                
                return Ok(ApiResponse<EfficiencyMetrics>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<EfficiencyMetrics>.InternalServerError($"Error calculating efficiency metrics: {ex.Message}"));
            }
        }

        /// <summary>
        /// Perform quality analysis based on production data
        /// </summary>
        [HttpGet("quality")]
        public async Task<ActionResult<ApiResponse<QualityAnalysis>>> GetQualityAnalysis([FromQuery] QualityFilter filter)
        {
            try
            {
                if (filter.StartDate >= filter.EndDate)
                    return BadRequest(ApiResponse<QualityAnalysis>.BadRequest("Start date must be before end date"));

                var result = await _statisticsService.PerformQualityAnalysisAsync(filter);
                
                return Ok(ApiResponse<QualityAnalysis>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<QualityAnalysis>.InternalServerError($"Error performing quality analysis: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get production summary for dashboard display
        /// </summary>
        [HttpGet("dashboard-summary")]
        public async Task<ActionResult<ApiResponse<DashboardSummary>>> GetDashboardSummary([FromQuery] DashboardFilter filter)
        {
            try
            {
                var result = await _statisticsService.GetDashboardSummaryAsync(filter);
                
                return Ok(ApiResponse<DashboardSummary>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<DashboardSummary>.InternalServerError($"Error getting dashboard summary: {ex.Message}"));
            }
        }

        /// <summary>
        /// Calculate OEE (Overall Equipment Effectiveness) for a specific device
        /// </summary>
        [HttpGet("oee")]
        public async Task<ActionResult<ApiResponse<OeeMetrics>>> GetOeeMetrics(
            [FromQuery] int deviceId,
            [FromQuery] DateTime date)
        {
            try
            {
                if (deviceId <= 0)
                    return BadRequest(ApiResponse<OeeMetrics>.BadRequest("Invalid device ID"));

                var result = await _statisticsService.CalculateOeeAsync(deviceId, date);
                
                return Ok(ApiResponse<OeeMetrics>.Success(result));
            }
            catch (KeyNotFoundException ex)
            {
                return NotFound(ApiResponse<OeeMetrics>.NotFound(ex.Message));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<OeeMetrics>.InternalServerError($"Error calculating OEE metrics: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get production forecasts based on historical data
        /// </summary>
        [HttpGet("forecast")]
        public async Task<ActionResult<ApiResponse<ProductionForecast>>> GetProductionForecast([FromQuery] ForecastFilter filter)
        {
            try
            {
                if (filter.DeviceId <= 0)
                    return BadRequest(ApiResponse<ProductionForecast>.BadRequest("Invalid device ID"));

                if (filter.DaysToForecast <= 0 || filter.DaysToForecast > 365)
                    return BadRequest(ApiResponse<ProductionForecast>.BadRequest("Days to forecast must be between 1 and 365"));

                var result = await _statisticsService.GenerateProductionForecastAsync(filter);
                
                return Ok(ApiResponse<ProductionForecast>.Success(result));
            }
            catch (KeyNotFoundException ex)
            {
                return NotFound(ApiResponse<ProductionForecast>.NotFound(ex.Message));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<ProductionForecast>.InternalServerError($"Error generating production forecast: {ex.Message}"));
            }
        }

        /// <summary>
        /// Detect production anomalies and outliers
        /// </summary>
        [HttpGet("anomalies")]
        public async Task<ActionResult<ApiResponse<AnomalyAnalysis>>> DetectProductionAnomalies([FromQuery] AnomalyFilter filter)
        {
            try
            {
                if (filter.StartDate >= filter.EndDate)
                    return BadRequest(ApiResponse<AnomalyAnalysis>.BadRequest("Start date must be before end date"));

                var result = await _statisticsService.DetectProductionAnomaliesAsync(filter);
                
                return Ok(ApiResponse<AnomalyAnalysis>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<AnomalyAnalysis>.InternalServerError($"Error detecting production anomalies: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get available devices for statistics
        /// </summary>
        [HttpGet("devices")]
        public async Task<ActionResult<ApiResponse<List<DeviceSummary>>>> GetAvailableDevices([FromQuery] bool activeOnly = true)
        {
            try
            {
                // This would typically get devices from device service
                // For now, returning empty list
                var result = new List<DeviceSummary>();
                
                return Ok(ApiResponse<List<DeviceSummary>>.Success(result));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<List<DeviceSummary>>.InternalServerError($"Error getting available devices: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get production summary for multiple devices
        /// </summary>
        [HttpGet("multi-device-summary")]
        public async Task<ActionResult<ApiResponse<MultiDeviceSummary>>> GetMultiDeviceSummary([FromQuery] List<int> 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<MultiDeviceSummary>.Success(multiDeviceSummary));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<MultiDeviceSummary>.InternalServerError($"Error getting multi-device summary: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get historical production data for charting
        /// </summary>
        [HttpGet("historical-data")]
        public async Task<ActionResult<ApiResponse<HistoricalProductionData>>> GetHistoricalProductionData(
            [FromQuery] int deviceId,
            [FromQuery] DateTime startDate,
            [FromQuery] DateTime endDate,
            [FromQuery] GroupBy groupBy = GroupBy.Date)
        {
            try
            {
                if (deviceId <= 0)
                    return BadRequest(ApiResponse<HistoricalProductionData>.BadRequest("Invalid device ID"));

                if (startDate >= endDate)
                    return BadRequest(ApiResponse<HistoricalProductionData>.BadRequest("Start date must be before end date"));

                var filter = new ReportFilter
                {
                    DeviceIds = new List<int> { 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<HistoricalProductionData>.Success(historicalData));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<HistoricalProductionData>.InternalServerError($"Error getting historical production data: {ex.Message}"));
            }
        }

        /// <summary>
        /// Get production efficiency trends over time
        /// </summary>
        [HttpGet("efficiency-trends")]
        public async Task<ActionResult<ApiResponse<EfficiencyTrendData>>> GetEfficiencyTrends(
            [FromQuery] int deviceId,
            [FromQuery] DateTime startDate,
            [FromQuery] DateTime endDate,
            [FromQuery] EfficiencyMetric metric = EfficiencyMetric.Oee)
        {
            try
            {
                if (deviceId <= 0)
                    return BadRequest(ApiResponse<EfficiencyTrendData>.BadRequest("Invalid device ID"));

                if (startDate >= endDate)
                    return BadRequest(ApiResponse<EfficiencyTrendData>.BadRequest("Start date must be before end date"));

                var filter = new EfficiencyFilter
                {
                    DeviceIds = new List<int> { 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<EfficiencyTrendData>.Success(trendData));
            }
            catch (Exception ex)
            {
                return StatusCode(500, ApiResponse<EfficiencyTrendData>.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<DeviceSummary> 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<DataPoint> 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<EfficiencyDataPoint> 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; }
    }
}