using Apollinare.Domain.Entities;
using Apollinare.Infrastructure.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Apollinare.API.Controllers;

[ApiController]
[Route("api/eventi/{eventoId}")]
public class EventoDetailsController : ControllerBase
{
    private readonly AppollinareDbContext _context;

    public EventoDetailsController(AppollinareDbContext context)
    {
        _context = context;
    }

    // OSPITI
    [HttpGet("ospiti")]
    public async Task<ActionResult<IEnumerable<EventoDettaglioOspiti>>> GetOspiti(int eventoId)
    {
        return await _context.EventiDettaglioOspiti
            .Include(o => o.TipoOspite)
            .Where(o => o.EventoId == eventoId)
            .ToListAsync();
    }

    [HttpPost("ospiti")]
    public async Task<ActionResult<EventoDettaglioOspiti>> AddOspite(int eventoId, EventoDettaglioOspiti ospite)
    {
        ospite.EventoId = eventoId;
        ospite.CreatedAt = DateTime.UtcNow;
        _context.EventiDettaglioOspiti.Add(ospite);
        await _context.SaveChangesAsync();
        await AggiornaNumeroOspiti(eventoId);
        return CreatedAtAction(nameof(GetOspiti), new { eventoId }, ospite);
    }

    [HttpPut("ospiti/{id}")]
    public async Task<IActionResult> UpdateOspite(int eventoId, int id, EventoDettaglioOspiti ospite)
    {
        if (id != ospite.Id || eventoId != ospite.EventoId)
            return BadRequest();

        ospite.UpdatedAt = DateTime.UtcNow;
        _context.Entry(ospite).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        await AggiornaNumeroOspiti(eventoId);
        return NoContent();
    }

    [HttpDelete("ospiti/{id}")]
    public async Task<IActionResult> DeleteOspite(int eventoId, int id)
    {
        var ospite = await _context.EventiDettaglioOspiti.FindAsync(id);
        if (ospite == null || ospite.EventoId != eventoId)
            return NotFound();

        _context.EventiDettaglioOspiti.Remove(ospite);
        await _context.SaveChangesAsync();
        await AggiornaNumeroOspiti(eventoId);
        return NoContent();
    }

    // PRELIEVO (Lista Materiali)
    [HttpGet("prelievo")]
    public async Task<ActionResult<IEnumerable<EventoDettaglioPrelievo>>> GetPrelievo(int eventoId)
    {
        return await _context.EventiDettaglioPrelievo
            .Include(p => p.Articolo)
                .ThenInclude(a => a!.TipoMateriale)
            .Where(p => p.EventoId == eventoId)
            .ToListAsync();
    }

    [HttpPost("prelievo")]
    public async Task<ActionResult<EventoDettaglioPrelievo>> AddPrelievo(int eventoId, EventoDettaglioPrelievo prelievo)
    {
        prelievo.EventoId = eventoId;
        prelievo.CreatedAt = DateTime.UtcNow;
        _context.EventiDettaglioPrelievo.Add(prelievo);
        await _context.SaveChangesAsync();
        return CreatedAtAction(nameof(GetPrelievo), new { eventoId }, prelievo);
    }

    [HttpPut("prelievo/{id}")]
    public async Task<IActionResult> UpdatePrelievo(int eventoId, int id, EventoDettaglioPrelievo prelievo)
    {
        if (id != prelievo.Id || eventoId != prelievo.EventoId)
            return BadRequest();

        prelievo.UpdatedAt = DateTime.UtcNow;
        _context.Entry(prelievo).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return NoContent();
    }

    [HttpDelete("prelievo/{id}")]
    public async Task<IActionResult> DeletePrelievo(int eventoId, int id)
    {
        var prelievo = await _context.EventiDettaglioPrelievo.FindAsync(id);
        if (prelievo == null || prelievo.EventoId != eventoId)
            return NotFound();

        _context.EventiDettaglioPrelievo.Remove(prelievo);
        await _context.SaveChangesAsync();
        return NoContent();
    }

    // RISORSE (Staff)
    [HttpGet("risorse")]
    public async Task<ActionResult<IEnumerable<EventoDettaglioRisorsa>>> GetRisorse(int eventoId)
    {
        return await _context.EventiDettaglioRisorse
            .Include(r => r.Risorsa)
                .ThenInclude(r => r!.TipoRisorsa)
            .Where(r => r.EventoId == eventoId)
            .ToListAsync();
    }

    [HttpPost("risorse")]
    public async Task<ActionResult<EventoDettaglioRisorsa>> AddRisorsa(int eventoId, EventoDettaglioRisorsa risorsa)
    {
        risorsa.EventoId = eventoId;
        risorsa.CreatedAt = DateTime.UtcNow;
        _context.EventiDettaglioRisorse.Add(risorsa);
        await _context.SaveChangesAsync();
        return CreatedAtAction(nameof(GetRisorse), new { eventoId }, risorsa);
    }

    [HttpPut("risorse/{id}")]
    public async Task<IActionResult> UpdateRisorsa(int eventoId, int id, EventoDettaglioRisorsa risorsa)
    {
        if (id != risorsa.Id || eventoId != risorsa.EventoId)
            return BadRequest();

        risorsa.UpdatedAt = DateTime.UtcNow;
        _context.Entry(risorsa).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return NoContent();
    }

    [HttpDelete("risorse/{id}")]
    public async Task<IActionResult> DeleteRisorsa(int eventoId, int id)
    {
        var risorsa = await _context.EventiDettaglioRisorse.FindAsync(id);
        if (risorsa == null || risorsa.EventoId != eventoId)
            return NotFound();

        _context.EventiDettaglioRisorse.Remove(risorsa);
        await _context.SaveChangesAsync();
        return NoContent();
    }

    // ACCONTI
    [HttpGet("acconti")]
    public async Task<ActionResult<IEnumerable<EventoAcconto>>> GetAcconti(int eventoId)
    {
        return await _context.EventiAcconti
            .Where(a => a.EventoId == eventoId)
            .OrderBy(a => a.Ordine)
            .ToListAsync();
    }

    [HttpPost("acconti")]
    public async Task<ActionResult<EventoAcconto>> AddAcconto(int eventoId, EventoAcconto acconto)
    {
        acconto.EventoId = eventoId;
        acconto.CreatedAt = DateTime.UtcNow;
        _context.EventiAcconti.Add(acconto);
        await _context.SaveChangesAsync();
        await RicalcolaAcconti(eventoId);
        return CreatedAtAction(nameof(GetAcconti), new { eventoId }, acconto);
    }

    [HttpPut("acconti/{id}")]
    public async Task<IActionResult> UpdateAcconto(int eventoId, int id, EventoAcconto acconto)
    {
        if (id != acconto.Id || eventoId != acconto.EventoId)
            return BadRequest();

        acconto.UpdatedAt = DateTime.UtcNow;
        _context.Entry(acconto).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        await RicalcolaAcconti(eventoId);
        return NoContent();
    }

    [HttpDelete("acconti/{id}")]
    public async Task<IActionResult> DeleteAcconto(int eventoId, int id)
    {
        var acconto = await _context.EventiAcconti.FindAsync(id);
        if (acconto == null || acconto.EventoId != eventoId)
            return NotFound();

        _context.EventiAcconti.Remove(acconto);
        await _context.SaveChangesAsync();
        await RicalcolaAcconti(eventoId);
        return NoContent();
    }

    // ALTRI COSTI
    [HttpGet("altri-costi")]
    public async Task<ActionResult<IEnumerable<EventoAltroCosto>>> GetAltriCosti(int eventoId)
    {
        return await _context.EventiAltriCosti
            .Where(c => c.EventoId == eventoId)
            .ToListAsync();
    }

    [HttpPost("altri-costi")]
    public async Task<ActionResult<EventoAltroCosto>> AddAltroCosto(int eventoId, EventoAltroCosto costo)
    {
        costo.EventoId = eventoId;
        costo.CreatedAt = DateTime.UtcNow;
        _context.EventiAltriCosti.Add(costo);
        await _context.SaveChangesAsync();
        return CreatedAtAction(nameof(GetAltriCosti), new { eventoId }, costo);
    }

    [HttpPut("altri-costi/{id}")]
    public async Task<IActionResult> UpdateAltroCosto(int eventoId, int id, EventoAltroCosto costo)
    {
        if (id != costo.Id || eventoId != costo.EventoId)
            return BadRequest();

        costo.UpdatedAt = DateTime.UtcNow;
        _context.Entry(costo).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return NoContent();
    }

    [HttpDelete("altri-costi/{id}")]
    public async Task<IActionResult> DeleteAltroCosto(int eventoId, int id)
    {
        var costo = await _context.EventiAltriCosti.FindAsync(id);
        if (costo == null || costo.EventoId != eventoId)
            return NotFound();

        _context.EventiAltriCosti.Remove(costo);
        await _context.SaveChangesAsync();
        return NoContent();
    }

    // DEGUSTAZIONI
    [HttpGet("degustazioni")]
    public async Task<ActionResult<IEnumerable<EventoDegustazione>>> GetDegustazioni(int eventoId)
    {
        return await _context.EventiDegustazioni
            .Where(d => d.EventoId == eventoId)
            .OrderBy(d => d.DataDegustazione)
            .ToListAsync();
    }

    [HttpPost("degustazioni")]
    public async Task<ActionResult<EventoDegustazione>> AddDegustazione(int eventoId, EventoDegustazione degustazione)
    {
        degustazione.EventoId = eventoId;
        degustazione.CreatedAt = DateTime.UtcNow;
        _context.EventiDegustazioni.Add(degustazione);
        await _context.SaveChangesAsync();
        return CreatedAtAction(nameof(GetDegustazioni), new { eventoId }, degustazione);
    }

    [HttpPut("degustazioni/{id}")]
    public async Task<IActionResult> UpdateDegustazione(int eventoId, int id, EventoDegustazione degustazione)
    {
        if (id != degustazione.Id || eventoId != degustazione.EventoId)
            return BadRequest();

        degustazione.UpdatedAt = DateTime.UtcNow;
        _context.Entry(degustazione).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return NoContent();
    }

    [HttpDelete("degustazioni/{id}")]
    public async Task<IActionResult> DeleteDegustazione(int eventoId, int id)
    {
        var degustazione = await _context.EventiDegustazioni.FindAsync(id);
        if (degustazione == null || degustazione.EventoId != eventoId)
            return NotFound();

        _context.EventiDegustazioni.Remove(degustazione);
        await _context.SaveChangesAsync();
        return NoContent();
    }

    // Helper methods
    private async Task AggiornaNumeroOspiti(int eventoId)
    {
        var evento = await _context.Eventi
            .Include(e => e.DettagliOspiti)
                .ThenInclude(o => o.TipoOspite)
            .FirstOrDefaultAsync(e => e.Id == eventoId);

        if (evento != null)
        {
            evento.NumeroOspitiAdulti = evento.DettagliOspiti
                .Where(o => o.TipoOspite?.Codice == "ADULTO")
                .Sum(o => o.Numero);
            evento.NumeroOspitiBambini = evento.DettagliOspiti
                .Where(o => o.TipoOspite?.Codice == "BAMBINO")
                .Sum(o => o.Numero);
            evento.NumeroOspiti = evento.DettagliOspiti.Sum(o => o.Numero);
            evento.UpdatedAt = DateTime.UtcNow;
            await _context.SaveChangesAsync();
        }
    }

    private async Task RicalcolaAcconti(int eventoId)
    {
        var evento = await _context.Eventi
            .Include(e => e.Acconti)
            .FirstOrDefaultAsync(e => e.Id == eventoId);

        if (evento != null)
        {
            evento.TotaleAcconti = evento.Acconti.Sum(a => a.Importo);
            evento.Saldo = (evento.CostoTotale ?? 0) - (evento.TotaleAcconti ?? 0);
            evento.UpdatedAt = DateTime.UtcNow;
            await _context.SaveChangesAsync();
        }
    }
}
