using Microsoft.EntityFrameworkCore;
using foundation_system.Data;
using foundation_system.Models.ViewModels;

namespace foundation_system.Services;

public class DashboardService : IDashboardService
{
    private readonly ApplicationDbContext _context;

    public DashboardService(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<List<string>> GetUserPermissionCodesAsync(long userId)
    {
        // Get all permission codes for the user through their roles
        var permissionCodes = await _context.RolesUsuario
            .Where(ru => ru.UsuarioId == userId)
            .Join(_context.RolesPermisos, ru => ru.RolId, rp => rp.RolId, (ru, rp) => rp.PermisoId)
            .Join(_context.Permisos, permisoId => permisoId, p => p.Id, (permisoId, p) => p.Codigo)
            .Distinct()
            .ToListAsync();

        return permissionCodes;
    }

    public async Task<bool> UserHasPermissionAsync(long userId, string permisoCodigo)
    {
        var codes = await GetUserPermissionCodesAsync(userId);
        // Check if user has a permission that starts with the given code (e.g., "Expediente" matches "Expediente.Index")
        return codes.Any(c => c.StartsWith(permisoCodigo, StringComparison.OrdinalIgnoreCase));
    }

    public async Task<DashboardViewModel> GetDashboardDataAsync(long userId)
    {
        var vm = new DashboardViewModel();
        
        // Check if user is ROOT (has all permissions)
        var isRoot = await _context.RolesUsuario
            .Where(ru => ru.UsuarioId == userId)
            .Join(_context.RolesSistema, ru => ru.RolId, r => r.Id, (ru, r) => r.Codigo)
            .AnyAsync(codigo => codigo == "ROOT");

        var permissionCodes = await GetUserPermissionCodesAsync(userId);

        // Set permission flags
        vm.TienePermisoExpediente = isRoot || permissionCodes.Any(c => c.StartsWith("Expediente", StringComparison.OrdinalIgnoreCase));
        vm.TienePermisoAsistencia = isRoot || permissionCodes.Any(c => c.StartsWith("Asistencia", StringComparison.OrdinalIgnoreCase));
        vm.TienePermisoCajaChica = isRoot || permissionCodes.Any(c => 
            c.StartsWith("CajaChica", StringComparison.OrdinalIgnoreCase) || 
            c.StartsWith("MovimientoCaja", StringComparison.OrdinalIgnoreCase));

        // Expediente Stats
        if (vm.TienePermisoExpediente)
        {
            vm.TotalNinosActivos = await _context.Ninos.CountAsync(n => n.Activo);

            var today = DateTime.Today;
            var currentMonth = today.Month;

            // Birthday list for current month
            var cumpleaneros = await _context.Ninos
                .Where(n => n.Activo)
                .Include(n => n.Persona)
                .Where(n => n.Persona.FechaNacimiento != null && n.Persona.FechaNacimiento.Value.Month == currentMonth)
                .Select(n => new {
                    n.Persona.Nombres,
                    n.Persona.Apellidos,
                    n.Persona.FechaNacimiento
                })
                .ToListAsync();

            vm.CumpleanerosMes = cumpleaneros.Count;
            vm.ListaCumpleaneros = cumpleaneros.Select(c => new NinoCumpleanero
            {
                NombreCompleto = $"{c.Nombres} {c.Apellidos}",
                Edad = today.Year - c.FechaNacimiento!.Value.Year,
                DiaCumple = c.FechaNacimiento.Value.Day
            }).OrderBy(c => c.DiaCumple).ToList();

            // Children older than 14
            var cutoffDate = DateOnly.FromDateTime(today.AddYears(-14));
            vm.NinosMayores14 = await _context.Ninos
                .Where(n => n.Activo)
                .Include(n => n.Persona)
                .CountAsync(n => n.Persona.FechaNacimiento != null && n.Persona.FechaNacimiento <= cutoffDate);
        }

        // Attendance Stats
        if (vm.TienePermisoAsistencia)
        {
            var today = DateOnly.FromDateTime(DateTime.Today);
            vm.TotalNinosParaAsistencia = await _context.Ninos.CountAsync(n => n.Activo);
            vm.AsistenciasHoy = await _context.Asistencias
                .CountAsync(a => a.Fecha == today && a.Estado == "PRESENTE");
            
            vm.PorcentajeAsistenciaHoy = vm.TotalNinosParaAsistencia > 0 
                ? Math.Round((decimal)vm.AsistenciasHoy / vm.TotalNinosParaAsistencia * 100, 1) 
                : 0;
        }

        // Petty Cash Stats
        if (vm.TienePermisoCajaChica)
        {
            var cajaActiva = await _context.CajasChicas
                .Where(c => c.Estado == "ABIERTA")
                .FirstOrDefaultAsync();

            if (cajaActiva != null)
            {
                vm.NombreCajaActiva = cajaActiva.Nombre;
                vm.SaldoCajaChica = cajaActiva.SaldoActual;

                var inicioMes = new DateOnly(DateTime.Today.Year, DateTime.Today.Month, 1);
                var finMes = inicioMes.AddMonths(1).AddDays(-1);

                var movimientosMes = await _context.CajaChicaMovimientos
                    .Where(m => m.CajaChicaId == cajaActiva.Id && 
                                m.FechaMovimiento >= inicioMes && 
                                m.FechaMovimiento <= finMes)
                    .ToListAsync();

                vm.MovimientosMes = movimientosMes.Count;
                vm.GastosMes = movimientosMes
                    .Where(m => m.TipoMovimiento == "GASTO")
                    .Sum(m => m.Monto);
            }
        }

        return vm;
    }
}
