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

namespace Apollinare.API.Controllers;

[ApiController]
[Route("api/report-templates")]
public class ReportTemplatesController : ControllerBase
{
    private readonly AppollinareDbContext _context;
    private readonly ReportGeneratorService _reportGenerator;

    public ReportTemplatesController(AppollinareDbContext context, ReportGeneratorService reportGenerator)
    {
        _context = context;
        _reportGenerator = reportGenerator;
    }

    [HttpGet]
    public async Task<ActionResult<List<ReportTemplateDto>>> GetAll([FromQuery] string? categoria = null)
    {
        var query = _context.ReportTemplates.AsQueryable();

        if (!string.IsNullOrEmpty(categoria))
        {
            query = query.Where(t => t.Categoria == categoria);
        }

        var templates = await query
            .Where(t => t.Attivo)
            .OrderBy(t => t.Categoria)
            .ThenBy(t => t.Nome)
            .Select(t => new ReportTemplateDto
            {
                Id = t.Id,
                Nome = t.Nome,
                Descrizione = t.Descrizione,
                Categoria = t.Categoria,
                PageSize = t.PageSize,
                Orientation = t.Orientation,
                Attivo = t.Attivo,
                CreatedAt = t.CreatedAt,
                UpdatedAt = t.UpdatedAt,
                ThumbnailBase64 = t.Thumbnail != null ? Convert.ToBase64String(t.Thumbnail) : null
            })
            .ToListAsync();

        return templates;
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<ReportTemplateDto>> GetById(int id)
    {
        var template = await _context.ReportTemplates.FindAsync(id);
        if (template == null)
            return NotFound();

        return new ReportTemplateDto
        {
            Id = template.Id,
            Nome = template.Nome,
            Descrizione = template.Descrizione,
            Categoria = template.Categoria,
            TemplateJson = template.TemplateJson,
            PageSize = template.PageSize,
            Orientation = template.Orientation,
            Attivo = template.Attivo,
            CreatedAt = template.CreatedAt,
            UpdatedAt = template.UpdatedAt,
            ThumbnailBase64 = template.Thumbnail != null ? Convert.ToBase64String(template.Thumbnail) : null
        };
    }

    [HttpPost]
    public async Task<ActionResult<ReportTemplateDto>> Create([FromBody] ReportTemplateDto dto)
    {
        var template = new ReportTemplate
        {
            Nome = dto.Nome,
            Descrizione = dto.Descrizione,
            Categoria = dto.Categoria,
            TemplateJson = dto.TemplateJson,
            PageSize = dto.PageSize,
            Orientation = dto.Orientation,
            Attivo = dto.Attivo,
            CreatedAt = DateTime.UtcNow
        };

        if (!string.IsNullOrEmpty(dto.ThumbnailBase64))
        {
            template.Thumbnail = Convert.FromBase64String(dto.ThumbnailBase64);
            template.ThumbnailMimeType = "image/png";
        }

        _context.ReportTemplates.Add(template);
        await _context.SaveChangesAsync();

        dto.Id = template.Id;
        dto.CreatedAt = template.CreatedAt;

        return CreatedAtAction(nameof(GetById), new { id = template.Id }, dto);
    }

    [HttpPut("{id}")]
    public async Task<ActionResult<ReportTemplateDto>> Update(int id, [FromBody] ReportTemplateDto dto)
    {
        var template = await _context.ReportTemplates.FindAsync(id);
        if (template == null)
            return NotFound();

        template.Nome = dto.Nome;
        template.Descrizione = dto.Descrizione;
        template.Categoria = dto.Categoria;
        template.TemplateJson = dto.TemplateJson;
        template.PageSize = dto.PageSize;
        template.Orientation = dto.Orientation;
        template.Attivo = dto.Attivo;
        template.UpdatedAt = DateTime.UtcNow;

        if (!string.IsNullOrEmpty(dto.ThumbnailBase64))
        {
            template.Thumbnail = Convert.FromBase64String(dto.ThumbnailBase64);
            template.ThumbnailMimeType = "image/png";
        }

        await _context.SaveChangesAsync();

        dto.UpdatedAt = template.UpdatedAt;
        return dto;
    }

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

        _context.ReportTemplates.Remove(template);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    [HttpPost("{id}/clone")]
    public async Task<ActionResult<ReportTemplateDto>> Clone(int id)
    {
        var original = await _context.ReportTemplates.FindAsync(id);
        if (original == null)
            return NotFound();

        var clone = new ReportTemplate
        {
            Nome = $"{original.Nome} (copia)",
            Descrizione = original.Descrizione,
            Categoria = original.Categoria,
            TemplateJson = original.TemplateJson,
            Thumbnail = original.Thumbnail,
            ThumbnailMimeType = original.ThumbnailMimeType,
            PageSize = original.PageSize,
            Orientation = original.Orientation,
            Attivo = true,
            CreatedAt = DateTime.UtcNow
        };

        _context.ReportTemplates.Add(clone);
        await _context.SaveChangesAsync();

        return new ReportTemplateDto
        {
            Id = clone.Id,
            Nome = clone.Nome,
            Descrizione = clone.Descrizione,
            Categoria = clone.Categoria,
            TemplateJson = clone.TemplateJson,
            PageSize = clone.PageSize,
            Orientation = clone.Orientation,
            Attivo = clone.Attivo,
            CreatedAt = clone.CreatedAt,
            ThumbnailBase64 = clone.Thumbnail != null ? Convert.ToBase64String(clone.Thumbnail) : null
        };
    }

    [HttpGet("{id}/export")]
    public async Task<IActionResult> Export(int id)
    {
        var template = await _context.ReportTemplates.FindAsync(id);
        if (template == null)
            return NotFound();

        // Return template JSON as .aprt file
        var fileName = $"{template.Nome.Replace(" ", "_")}.aprt";
        return File(System.Text.Encoding.UTF8.GetBytes(template.TemplateJson), "application/json", fileName);
    }

    [HttpPost("import")]
    public async Task<ActionResult<ReportTemplateDto>> Import(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("No file provided");

        using var reader = new StreamReader(file.OpenReadStream());
        var json = await reader.ReadToEndAsync();

        // Validate JSON structure
        try
        {
            var parsed = System.Text.Json.JsonSerializer.Deserialize<AprtTemplate>(json);
            if (parsed == null)
                return BadRequest("Invalid template format");

            var template = new ReportTemplate
            {
                Nome = parsed.Meta.Name ?? Path.GetFileNameWithoutExtension(file.FileName),
                Descrizione = parsed.Meta.Description,
                Categoria = "Importato",
                TemplateJson = json,
                PageSize = parsed.Meta.PageSize,
                Orientation = parsed.Meta.Orientation,
                Attivo = true,
                CreatedAt = DateTime.UtcNow
            };

            _context.ReportTemplates.Add(template);
            await _context.SaveChangesAsync();

            return new ReportTemplateDto
            {
                Id = template.Id,
                Nome = template.Nome,
                Descrizione = template.Descrizione,
                Categoria = template.Categoria,
                TemplateJson = template.TemplateJson,
                PageSize = template.PageSize,
                Orientation = template.Orientation,
                Attivo = template.Attivo,
                CreatedAt = template.CreatedAt
            };
        }
        catch (System.Text.Json.JsonException)
        {
            return BadRequest("Invalid JSON format");
        }
    }

    [HttpGet("categories")]
    public async Task<ActionResult<List<string>>> GetCategories()
    {
        var categories = await _context.ReportTemplates
            .Where(t => t.Attivo)
            .Select(t => t.Categoria)
            .Distinct()
            .OrderBy(c => c)
            .ToListAsync();

        return categories;
    }
}
