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

namespace Apollinare.API.Controllers;

[ApiController]
[Route("api/[controller]")]
public class RisorseController : ControllerBase
{
    private readonly AppollinareDbContext _context;

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

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Risorsa>>> GetRisorse(
        [FromQuery] string? search,
        [FromQuery] int? tipoRisorsaId,
        [FromQuery] bool? attivo)
    {
        var query = _context.Risorse
            .Include(r => r.TipoRisorsa)
            .AsQueryable();

        if (!string.IsNullOrEmpty(search))
            query = query.Where(r => r.Nome.Contains(search) ||
                                     (r.Cognome != null && r.Cognome.Contains(search)));

        if (tipoRisorsaId.HasValue)
            query = query.Where(r => r.TipoRisorsaId == tipoRisorsaId.Value);

        if (attivo.HasValue)
            query = query.Where(r => r.Attivo == attivo.Value);

        return await query.OrderBy(r => r.Cognome).ThenBy(r => r.Nome).ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Risorsa>> GetRisorsa(int id)
    {
        var risorsa = await _context.Risorse
            .Include(r => r.TipoRisorsa)
            .FirstOrDefaultAsync(r => r.Id == id);

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

        return risorsa;
    }

    [HttpPost]
    public async Task<ActionResult<Risorsa>> CreateRisorsa(Risorsa risorsa)
    {
        risorsa.CreatedAt = DateTime.UtcNow;
        _context.Risorse.Add(risorsa);
        await _context.SaveChangesAsync();

        return CreatedAtAction(nameof(GetRisorsa), new { id = risorsa.Id }, risorsa);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateRisorsa(int id, Risorsa risorsa)
    {
        if (id != risorsa.Id)
            return BadRequest();

        risorsa.UpdatedAt = DateTime.UtcNow;
        _context.Entry(risorsa).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!await _context.Risorse.AnyAsync(r => r.Id == id))
                return NotFound();
            throw;
        }

        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteRisorsa(int id)
    {
        var risorsa = await _context.Risorse.FindAsync(id);
        if (risorsa == null)
            return NotFound();

        _context.Risorse.Remove(risorsa);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    [HttpGet("{id}/disponibilita")]
    public async Task<ActionResult<object>> GetDisponibilita(int id, [FromQuery] DateTime data)
    {
        var risorsa = await _context.Risorse.FindAsync(id);
        if (risorsa == null)
            return NotFound();

        var impegni = await _context.EventiDettaglioRisorse
            .Include(r => r.Evento)
            .Where(r => r.RisorsaId == id &&
                       r.Evento!.DataEvento.Date == data.Date &&
                       r.Evento.Stato != Domain.Enums.StatoEvento.Scheda)
            .Select(r => new
            {
                eventoId = r.EventoId,
                evento = r.Evento!.Descrizione,
                oraInizio = r.OraInizio,
                oraFine = r.OraFine
            })
            .ToListAsync();

        return Ok(new
        {
            risorsaId = id,
            data = data,
            impegni = impegni,
            disponibile = !impegni.Any()
        });
    }
}
