using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Haoliang.Data;
using Haoliang.Data.Entities;
using Haoliang.Models.Production;
using Haoliang.Data.Repositories;

namespace Haoliang.Data.Repositories
{
    public interface IProductionSummaryRepository : IRepository<ProductionSummary>
    {
        Task<ProductionSummary> GetByDateAsync(DateTime date);
        Task<IEnumerable<ProductionSummary>> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
        Task<ProductionSummary> GetByDeviceAndDateAsync(int deviceId, DateTime date);
        Task<ProductionSummary> GetTodaySummaryAsync();
        Task<ProductionSummary> GetYesterdaySummaryAsync();
        Task<WeeklyProductionSummary> GetWeeklySummaryAsync(DateTime weekStart);
        Task<MonthlyProductionSummary> GetMonthlySummaryAsync(int year, int month);
        Task<ProductionSummary> GetBestPerformingDeviceAsync(DateTime date);
        Task<ProductionSummary> GetWorstPerformingDeviceAsync(DateTime date);
        Task ArchiveProductionSummariesAsync(int daysToKeep = 90);
    }

    public class ProductionSummaryRepository : Repository<ProductionSummary>, IProductionSummaryRepository
    {
        private readonly CNCDbContext _context;

        public ProductionSummaryRepository(CNCDbContext context) : base(context)
        {
            _context = context;
        }

        public async Task<ProductionSummary> GetByDateAsync(DateTime date)
        {
            var startOfDay = date.Date;
            var endOfDay = startOfDay.AddDays(1);

            return await _context.ProductionSummaries
                .FirstOrDefaultAsync(s => s.ProductionDate >= startOfDay && 
                                        s.ProductionDate < endOfDay);
        }

        public async Task<IEnumerable<ProductionSummary>> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            return await _context.ProductionSummaries
                .Where(s => s.ProductionDate >= startDate && 
                           s.ProductionDate <= endDate)
                .OrderBy(s => s.ProductionDate)
                .ThenBy(s => s.DeviceName)
                .ToListAsync();
        }

        public async Task<ProductionSummary> GetByDeviceAndDateAsync(int deviceId, DateTime date)
        {
            var startOfDay = date.Date;
            var endOfDay = startOfDay.AddDays(1);

            return await _context.ProductionSummaries
                .FirstOrDefaultAsync(s => s.DeviceId == deviceId && 
                                        s.ProductionDate >= startOfDay && 
                                        s.ProductionDate < endOfDay);
        }

        public async Task<ProductionSummary> GetTodaySummaryAsync()
        {
            return await GetByDateAsync(DateTime.Today);
        }

        public async Task<ProductionSummary> GetYesterdaySummaryAsync()
        {
            return await GetByDateAsync(DateTime.Today.AddDays(-1));
        }

        public async Task<WeeklyProductionSummary> GetWeeklySummaryAsync(DateTime weekStart)
        {
            var weekEnd = weekStart.AddDays(7);
            
            var summaries = await _context.ProductionSummaries
                .Where(s => s.ProductionDate >= weekStart && 
                           s.ProductionDate < weekEnd)
                .ToListAsync();

            var weeklySummary = new WeeklyProductionSummary
            {
                WeekStart = weekStart,
                WeekEnd = weekEnd,
                TotalDevices = summaries.Select(s => s.DeviceId).Distinct().Count(),
                TotalQuantity = summaries.Sum(s => s.TotalQuantity),
                AverageDailyQuantity = summaries.Any() ? (decimal)summaries.Average(s => s.TotalQuantity) : 0,
                DailySummaries = summaries
                    .GroupBy(s => s.ProductionDate)
                    .Select(g => new DailyProductionSummary
                    {
                        Date = g.Key,
                        TotalQuantity = g.Sum(s => s.TotalQuantity),
                        DeviceCount = g.Select(s => s.DeviceId).Distinct().Count()
                    })
                    .OrderBy(d => d.Date)
                    .ToList()
            };

            return weeklySummary;
        }

        public async Task<MonthlyProductionSummary> GetMonthlySummaryAsync(int year, int month)
        {
            var monthStart = new DateTime(year, month, 1);
            var monthEnd = monthStart.AddMonths(1);

            var summaries = await _context.ProductionSummaries
                .Where(s => s.ProductionDate >= monthStart && 
                           s.ProductionDate < monthEnd)
                .ToListAsync();

            var monthlySummary = new MonthlyProductionSummary
            {
                Year = year,
                Month = month,
                TotalDevices = summaries.Select(s => s.DeviceId).Distinct().Count(),
                TotalQuantity = summaries.Sum(s => s.TotalQuantity),
                AverageDailyQuantity = summaries.Any() ? (decimal)summaries.Average(s => s.TotalQuantity) : 0,
                WeeklySummaries = new List<WeeklyProductionSummary>()
            };

            // Group by week
            var weeks = summaries
                .GroupBy(s => s.ProductionDate - TimeSpan.FromDays((int)s.ProductionDate.DayOfWeek))
                .ToList();

            foreach (var week in weeks)
            {
                var weeklySummary = new WeeklyProductionSummary
                {
                    WeekStart = week.Key,
                    WeekEnd = week.Key.AddDays(7),
                    TotalQuantity = week.Sum(s => s.TotalQuantity),
                    DailySummaries = week
                        .GroupBy(s => s.ProductionDate)
                        .Select(g => new DailyProductionSummary
                        {
                            Date = g.Key,
                            TotalQuantity = g.Sum(s => s.TotalQuantity),
                            DeviceCount = g.Select(s => s.DeviceId).Distinct().Count()
                        })
                        .OrderBy(d => d.Date)
                        .ToList()
                };
                monthlySummary.WeeklySummaries.Add(weeklySummary);
            }

            return monthlySummary;
        }

        public async Task<ProductionSummary> GetBestPerformingDeviceAsync(DateTime date)
        {
            var startOfDay = date.Date;
            var endOfDay = startOfDay.AddDays(1);

            var summaries = await _context.ProductionSummaries
                .Where(s => s.ProductionDate >= startOfDay && 
                           s.ProductionDate < endOfDay)
                .ToListAsync();

            if (!summaries.Any())
                return null;

            return summaries
                .OrderByDescending(s => s.TotalQuantity)
                .FirstOrDefault();
        }

        public async Task<ProductionSummary> GetWorstPerformingDeviceAsync(DateTime date)
        {
            var startOfDay = date.Date;
            var endOfDay = startOfDay.AddDays(1);

            var summaries = await _context.ProductionSummaries
                .Where(s => s.ProductionDate >= startOfDay && 
                           s.ProductionDate < endOfDay)
                .ToListAsync();

            if (!summaries.Any())
                return null;

            return summaries
                .OrderBy(s => s.TotalQuantity)
                .FirstOrDefault();
        }

        public async Task ArchiveProductionSummariesAsync(int daysToKeep = 90)
        {
            var cutoffDate = DateTime.Today.AddDays(-daysToKeep);
            
            var summariesToArchive = await _context.ProductionSummaries
                .Where(s => s.ProductionDate < cutoffDate)
                .ToListAsync();

            if (summariesToArchive.Any())
            {
                // In a real implementation, you would move these to an archive table
                _context.ProductionSummaries.RemoveRange(summariesToArchive);
                await SaveAsync();
            }
        }
    }
}