using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using foundation_system.Data;
using foundation_system.Models;
using foundation_system.Models.ViewModels;
using Microsoft.AspNetCore.Authorization;

namespace foundation_system.Controllers;

[Authorize]
public class AsistenciaController : Controller
{
    private readonly ApplicationDbContext _context;

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

    // GET: Asistencia
    public async Task<IActionResult> Index(int? año, int? mes, string? diasSemana)
    {
        int targetAnio = año ?? DateTime.Now.Year;
        int targetMes = mes ?? DateTime.Now.Month;
        
        var diasSeleccionadosList = string.IsNullOrEmpty(diasSemana) 
            ? new List<string> { "1", "2", "3", "4", "5" } 
            : diasSemana.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

        var firstDayOfMonth = new DateTime(targetAnio, targetMes, 1);
        var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

        var ninos = await _context.Ninos
            .Include(n => n.Persona)
            .Where(n => n.Activo && n.Estado == "ACTIVO")
            .OrderBy(n => n.Persona.Nombres)
            .ToListAsync();

        var firstDateOnly = DateOnly.FromDateTime(firstDayOfMonth);
        var lastDateOnly = DateOnly.FromDateTime(lastDayOfMonth);

        var asistencias = await _context.Asistencias
            .Where(a => a.Fecha >= firstDateOnly && a.Fecha <= lastDateOnly)
            .ToListAsync();

        var viewModel = new AsistenciaGridViewModel
        {
            Año = targetAnio,
            Mes = targetMes,
            NombreMes = firstDayOfMonth.ToString("MMMM", new System.Globalization.CultureInfo("es-ES")).ToUpper(),
            DiasSemanaSeleccionados = string.Join(",", diasSeleccionadosList),
            DiasDelMes = Enumerable.Range(0, lastDayOfMonth.Day)
                .Select(day => firstDayOfMonth.AddDays(day))
                .ToList(),
            Expedientes = ninos,
            Asistencias = asistencias.ToDictionary(
                a => $"{a.NinoId}_{a.Fecha:yyyy-MM-dd}",
                a => a.Estado switch {
                    "PRESENTE" => "P",
                    "TARDE" => "T",
                    "AUSENTE" => "F",
                    "JUSTIFICADO" => "J",
                    "ENFERMO" => "E",
                    _ => ""
                }
            )
        };

        ViewBag.Años = Enumerable.Range(DateTime.Now.Year - 5, 10)
            .Select(a => new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem 
            { 
                Value = a.ToString(), 
                Text = a.ToString(), 
                Selected = a == targetAnio 
            }).ToList();

        ViewBag.Meses = Enumerable.Range(1, 12)
            .Select(m => new Microsoft.AspNetCore.Mvc.Rendering.SelectListItem 
            { 
                Value = m.ToString(), 
                Text = new DateTime(2000, m, 1).ToString("MMMM", new System.Globalization.CultureInfo("es-ES")).ToUpper(),
                Selected = m == targetMes
            }).ToList();

        ViewBag.DiasSemana = new List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>
        {
            new() { Value = "1", Text = "Lunes" },
            new() { Value = "2", Text = "Martes" },
            new() { Value = "3", Text = "Miércoles" },
            new() { Value = "4", Text = "Jueves" },
            new() { Value = "5", Text = "Viernes" },
            new() { Value = "6", Text = "Sábado" },
            new() { Value = "0", Text = "Domingo" }
        };

        return View(viewModel);
    }

    [HttpGet]
    public async Task<JsonResult> ObtenerEstadisticas(int año, int mes)
    {
        var firstDay = new DateOnly(año, mes, 1);
        var lastDay = firstDay.AddMonths(1).AddDays(-1);

        var asistencias = await _context.Asistencias
            .Where(a => a.Fecha >= firstDay && a.Fecha <= lastDay)
            .ToListAsync();

        return Json(new
        {
            total = asistencias.Count,
            presentes = asistencias.Count(a => a.Estado == "PRESENTE"),
            tardes = asistencias.Count(a => a.Estado == "TARDE"),
            faltas = asistencias.Count(a => a.Estado == "AUSENTE"),
            justificados = asistencias.Count(a => a.Estado == "JUSTIFICADO"),
            enfermos = asistencias.Count(a => a.Estado == "ENFERMO")
        });
    }

    [HttpPost]
    public async Task<IActionResult> GuardarAsistencia(long expedienteId, DateOnly fecha, string estado)
    {
        string dbEstado = estado switch
        {
            "P" => "PRESENTE",
            "T" => "TARDE",
            "F" => "AUSENTE",
            "J" => "JUSTIFICADO",
            "E" => "ENFERMO",
            _ => ""
        };

        if (string.IsNullOrEmpty(dbEstado))
        {
            // Si el estado es vacío, podríamos borrar el registro o dejarlo como pendiente
            var existing = await _context.Asistencias
                .FirstOrDefaultAsync(a => a.NinoId == expedienteId && a.Fecha == fecha);
            if (existing != null)
            {
                _context.Asistencias.Remove(existing);
                await _context.SaveChangesAsync();
            }
            return Json(new { success = true });
        }

        var asistencia = await _context.Asistencias
            .FirstOrDefaultAsync(a => a.NinoId == expedienteId && a.Fecha == fecha);

        if (asistencia == null)
        {
            asistencia = new Asistencia
            {
                NinoId = expedienteId,
                Fecha = fecha,
                Estado = dbEstado,
                CreadoEn = DateTime.UtcNow
            };
            _context.Asistencias.Add(asistencia);
        }
        else
        {
            asistencia.Estado = dbEstado;
        }

        await _context.SaveChangesAsync();
        return Json(new { success = true });
    }

    [HttpPost]
    public async Task<IActionResult> GuardarAsistenciasMasivas([FromBody] List<AsistenciaInputModel> cambios)
    {
        foreach (var cambio in cambios)
        {
            string dbEstado = cambio.Estado switch
            {
                "P" => "PRESENTE",
                "T" => "TARDE",
                "F" => "AUSENTE",
                "J" => "JUSTIFICADO",
                "E" => "ENFERMO",
                _ => ""
            };

            var asistencia = await _context.Asistencias
                .FirstOrDefaultAsync(a => a.NinoId == cambio.ExpedienteId && a.Fecha == cambio.Fecha);

            if (string.IsNullOrEmpty(dbEstado))
            {
                if (asistencia != null) _context.Asistencias.Remove(asistencia);
            }
            else
            {
                if (asistencia == null)
                {
                    _context.Asistencias.Add(new Asistencia
                    {
                        NinoId = cambio.ExpedienteId,
                        Fecha = cambio.Fecha,
                        Estado = dbEstado,
                        CreadoEn = DateTime.UtcNow
                    });
                }
                else
                {
                    asistencia.Estado = dbEstado;
                }
            }
        }

        await _context.SaveChangesAsync();
        return Json(new { success = true, message = "Cambios guardados correctamente" });
    }

    [HttpGet]
    public async Task<IActionResult> ReporteMensual(int? año, int? mes, string? diasSemana)
    {
        int targetAnio = año ?? DateTime.Now.Year;
        int targetMes = mes ?? DateTime.Now.Month;

        var firstDayOfMonth = new DateTime(targetAnio, targetMes, 1);
        var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

        var ninos = await _context.Ninos
            .Include(n => n.Persona)
            .Where(n => n.Activo && n.Estado == "ACTIVO")
            .OrderBy(n => n.Persona.Nombres)
            .ToListAsync();

        var firstDateOnly = DateOnly.FromDateTime(firstDayOfMonth);
        var lastDateOnly = DateOnly.FromDateTime(lastDayOfMonth);

        var asistencias = await _context.Asistencias
            .Where(a => a.Fecha >= firstDateOnly && a.Fecha <= lastDateOnly)
            .ToListAsync();

        var viewModel = new AsistenciaGridViewModel
        {
            Año = targetAnio,
            Mes = targetMes,
            NombreMes = firstDayOfMonth.ToString("MMMM", new System.Globalization.CultureInfo("es-ES")).ToUpper(),
            DiasSemanaSeleccionados = diasSemana ?? "",
            DiasDelMes = Enumerable.Range(0, lastDayOfMonth.Day)
                .Select(day => firstDayOfMonth.AddDays(day))
                .ToList(),
            Expedientes = ninos,
            Asistencias = asistencias.ToDictionary(
                a => $"{a.NinoId}_{a.Fecha:yyyy-MM-dd}",
                a => a.Estado switch {
                    "PRESENTE" => "P",
                    "TARDE" => "T",
                    "AUSENTE" => "F",
                    "JUSTIFICADO" => "J",
                    "ENFERMO" => "E",
                    _ => ""
                }
            )
        };

        return View(viewModel);
    }

    [HttpGet]
    public async Task<IActionResult> ReporteIndividual(long ninoId, int? año, int? mes, string? diasSemana)
    {
        int targetAnio = año ?? DateTime.Now.Year;
        int targetMes = mes ?? DateTime.Now.Month;

        var firstDayOfMonth = new DateTime(targetAnio, targetMes, 1);
        var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

        var nino = await _context.Ninos
            .Include(n => n.Persona)
            .FirstOrDefaultAsync(n => n.Id == ninoId);

        if (nino == null) return NotFound();

        var firstDateOnly = DateOnly.FromDateTime(firstDayOfMonth);
        var lastDateOnly = DateOnly.FromDateTime(lastDayOfMonth);

        var asistencias = await _context.Asistencias
            .Where(a => a.NinoId == ninoId && a.Fecha >= firstDateOnly && a.Fecha <= lastDateOnly)
            .ToListAsync();

        var viewModel = new AsistenciaGridViewModel
        {
            Año = targetAnio,
            Mes = targetMes,
            NombreMes = firstDayOfMonth.ToString("MMMM", new System.Globalization.CultureInfo("es-ES")).ToUpper(),
            DiasSemanaSeleccionados = diasSemana ?? "",
            DiasDelMes = Enumerable.Range(0, lastDayOfMonth.Day)
                .Select(day => firstDayOfMonth.AddDays(day))
                .ToList(),
            Expedientes = new List<Nino> { nino },
            Asistencias = asistencias.ToDictionary(
                a => $"{a.NinoId}_{a.Fecha:yyyy-MM-dd}",
                a => a.Estado switch {
                    "PRESENTE" => "P",
                    "TARDE" => "T",
                    "AUSENTE" => "F",
                    "JUSTIFICADO" => "J",
                    "ENFERMO" => "E",
                    _ => ""
                }
            )
        };

        return View(viewModel);
    }

    [HttpGet]
    public IActionResult ExportarExcel(int año, int mes, string diasSemana)
    {
        // Placeholder for Excel export
        return File(new byte[0], "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"Asistencia_{año}_{mes}.xlsx");
    }
}

public class AsistenciaInputModel
{
    public long ExpedienteId { get; set; }
    public DateOnly Fecha { get; set; }
    public string Estado { get; set; } = string.Empty;
}

