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.System;
using Haoliang.Data.Repositories;

namespace Haoliang.Data.Repositories
{
    public interface ILogRepository : IRepository<LogEntry>
    {
        Task<IEnumerable<LogEntry>> GetLogsAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null, string category = null);
        Task<int> GetLogCountAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null);
        Task ArchiveLogsAsync(DateTime cutoffDate);
        Task ClearLogsAsync();
        Task<IEnumerable<LogEntry>> GetRecentLogsAsync(int count = 100);
        Task<IEnumerable<LogEntry>> GetErrorLogsAsync(DateTime? startDate = null, DateTime? endDate = null);
        Task<LogStatistics> GetLogStatisticsAsync(DateTime date);
        Task<bool> LogExistsAsync(int logId);
        Task<IEnumerable<LogEntry>> GetLogsBySourceAsync(string source);
    }

    public class LogRepository : Repository<LogEntry>, ILogRepository
    {
        private readonly CNCDbContext _context;

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

        public async Task<IEnumerable<LogEntry>> GetLogsAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null, string category = null)
        {
            var query = _context.LogEntries.AsQueryable();

            if (logLevel.HasValue)
            {
                query = query.Where(l => l.Level == logLevel.Value);
            }

            if (startDate.HasValue)
            {
                query = query.Where(l => l.Timestamp >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                query = query.Where(l => l.Timestamp <= endDate.Value);
            }

            if (!string.IsNullOrEmpty(category))
            {
                query = query.Where(l => l.Category == category);
            }

            return await query
                .OrderByDescending(l => l.Timestamp)
                .ToListAsync();
        }

        public async Task<int> GetLogCountAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _context.LogEntries.AsQueryable();

            if (logLevel.HasValue)
            {
                query = query.Where(l => l.Level == logLevel.Value);
            }

            if (startDate.HasValue)
            {
                query = query.Where(l => l.Timestamp >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                query = query.Where(l => l.Timestamp <= endDate.Value);
            }

            return await query.CountAsync();
        }

        public async Task ArchiveLogsAsync(DateTime cutoffDate)
        {
            var logsToArchive = await _context.LogEntries
                .Where(l => l.Timestamp < cutoffDate)
                .ToListAsync();

            if (logsToArchive.Any())
            {
                // In a real implementation, you would move these to an archive table or file
                // For now, we'll just delete them
                _context.LogEntries.RemoveRange(logsToArchive);
                await SaveAsync();
            }
        }

        public async Task ClearLogsAsync()
        {
            _context.LogEntries.RemoveRange(_context.LogEntries);
            await SaveAsync();
        }

        public async Task<IEnumerable<LogEntry>> GetRecentLogsAsync(int count = 100)
        {
            return await _context.LogEntries
                .OrderByDescending(l => l.Timestamp)
                .Take(count)
                .ToListAsync();
        }

        public async Task<IEnumerable<LogEntry>> GetErrorLogsAsync(DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _context.LogEntries
                .Where(l => l.Level == LogLevel.Error || l.Level == LogLevel.Critical);

            if (startDate.HasValue)
            {
                query = query.Where(l => l.Timestamp >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                query = query.Where(l => l.Timestamp <= endDate.Value);
            }

            return await query
                .OrderByDescending(l => l.Timestamp)
                .ToListAsync();
        }

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

            var logs = await _context.LogEntries
                .Where(l => l.Timestamp >= startOfDay && l.Timestamp <= endOfDay)
                .ToListAsync();

            var stats = new LogStatistics
            {
                Date = date,
                TotalLogs = logs.Count,
                ErrorLogs = logs.Count(l => l.Level == LogLevel.Error || l.Level == LogLevel.Critical),
                WarningLogs = logs.Count(l => l.Level == LogLevel.Warning),
                InfoLogs = logs.Count(l => l.Level == LogLevel.Information),
                DebugLogs = logs.Count(l => l.Level == LogLevel.Debug),
                LogSources = logs.GroupBy(l => l.Source)
                    .ToDictionary(g => g.Key, g => g.Count())
            };

            return stats;
        }

        public async Task<bool> LogExistsAsync(int logId)
        {
            return await _context.LogEntries
                .AnyAsync(l => l.Id == logId);
        }

        public async Task<IEnumerable<LogEntry>> GetLogsBySourceAsync(string source)
        {
            return await _context.LogEntries
                .Where(l => l.Source == source)
                .OrderByDescending(l => l.Timestamp)
                .ToListAsync();
        }
    }
}