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 ArticoliController : ControllerBase
{
    private readonly AppollinareDbContext _context;

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

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Articolo>>> GetArticoli(
        [FromQuery] string? search,
        [FromQuery] int? tipoMaterialeId,
        [FromQuery] int? categoriaId,
        [FromQuery] bool? attivo)
    {
        var query = _context.Articoli
            .Include(a => a.TipoMateriale)
            .Include(a => a.Categoria)
            .AsQueryable();

        if (!string.IsNullOrEmpty(search))
            query = query.Where(a => a.Codice.Contains(search) || a.Descrizione.Contains(search));

        if (tipoMaterialeId.HasValue)
            query = query.Where(a => a.TipoMaterialeId == tipoMaterialeId.Value);

        if (categoriaId.HasValue)
            query = query.Where(a => a.CategoriaId == categoriaId.Value);

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

        return await query.OrderBy(a => a.Descrizione).ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Articolo>> GetArticolo(int id)
    {
        var articolo = await _context.Articoli
            .Include(a => a.TipoMateriale)
            .Include(a => a.Categoria)
            .FirstOrDefaultAsync(a => a.Id == id);

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

        return articolo;
    }

    [HttpPost]
    public async Task<ActionResult<Articolo>> CreateArticolo(Articolo articolo)
    {
        articolo.CreatedAt = DateTime.UtcNow;
        _context.Articoli.Add(articolo);
        await _context.SaveChangesAsync();

        return CreatedAtAction(nameof(GetArticolo), new { id = articolo.Id }, articolo);
    }

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

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

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

        return NoContent();
    }

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

        _context.Articoli.Remove(articolo);
        await _context.SaveChangesAsync();

        return NoContent();
    }

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

        // Calcola quantità impegnata per quella data
        var qtaImpegnata = await _context.EventiDettaglioPrelievo
            .Include(p => p.Evento)
            .Where(p => p.ArticoloId == id &&
                       p.Evento!.DataEvento.Date == data.Date &&
                       p.Evento.Stato != Domain.Enums.StatoEvento.Scheda)
            .SumAsync(p => p.QtaEffettiva ?? p.QtaCalcolata ?? p.QtaRichiesta ?? 0);

        var qtaDisponibile = (articolo.QtaDisponibile ?? 0) - qtaImpegnata;

        return Ok(new
        {
            articoloId = id,
            data = data,
            qtaTotale = articolo.QtaDisponibile,
            qtaImpegnata = qtaImpegnata,
            qtaDisponibile = qtaDisponibile
        });
    }

    [HttpGet("{id}/immagine")]
    public async Task<IActionResult> GetImmagine(int id)
    {
        var articolo = await _context.Articoli.FindAsync(id);
        if (articolo?.Immagine == null)
            return NotFound();

        return File(articolo.Immagine, articolo.MimeType ?? "image/jpeg");
    }

    [HttpPost("{id}/immagine")]
    public async Task<IActionResult> UploadImmagine(int id, IFormFile file)
    {
        var articolo = await _context.Articoli.FindAsync(id);
        if (articolo == null)
            return NotFound();

        using var ms = new MemoryStream();
        await file.CopyToAsync(ms);
        articolo.Immagine = ms.ToArray();
        articolo.MimeType = file.ContentType;
        articolo.UpdatedAt = DateTime.UtcNow;

        await _context.SaveChangesAsync();

        return Ok();
    }
}
