using Microsoft.AspNetCore.Mvc;
using SIGCM.Domain.Entities;
using SIGCM.Domain.Interfaces;
using SIGCM.Infrastructure.Services;

namespace SIGCM.API.Controllers;

[ApiController]
[Route("api/[controller]")]
[Microsoft.AspNetCore.Authorization.Authorize]
public class ImagesController : ControllerBase
{
    private readonly IImageRepository _repository;
    private readonly IWebHostEnvironment _env;
    private readonly ImageOptimizationService _imageService;

    public ImagesController(
        IImageRepository repository, 
        IWebHostEnvironment env,
        ImageOptimizationService imageService)
    {
        _repository = repository;
        _env = env;
        _imageService = imageService;
    }

    /// <summary>
    /// Upload con optimización automática
    /// Genera: WebP principal, Thumbnail, Fallback JPEG
    /// </summary>
    [HttpPost("upload/{listingId}")]
    public async Task<IActionResult> Upload(int listingId, IFormFile file)
    {
        if (file == null || file.Length == 0) 
            return BadRequest("File is empty");

        // Validar extensiones permitidas
        var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".webp", ".gif" };
        var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
        if (!allowedExtensions.Contains(ext)) 
            return BadRequest("Invalid file type. Allowed: JPG, PNG, WebP, GIF");

        // Validar que sea realmente una imagen
        using var validationStream = file.OpenReadStream();
        var isValidImage = await _imageService.IsValidImageAsync(validationStream);
        if (!isValidImage)
            return BadRequest("File is not a valid image");

        // Configurar rutas
        string webRootPath = _env.WebRootPath ?? Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
        var uploadDir = Path.Combine(webRootPath, "uploads", "listings", listingId.ToString());
        
        if (!Directory.Exists(uploadDir))
        {
            Directory.CreateDirectory(uploadDir);
        }

        var baseFilename = Guid.NewGuid().ToString();

        // OPTIMIZAR LA IMAGEN
        using var stream = file.OpenReadStream();
        var optimization = await _imageService.OptimizeImageAsync(stream, file.FileName);

        if (!optimization.Success)
        {
            return StatusCode(500, new { Error = "Image optimization failed", Details = optimization.Error });
        }

        // 1. Guardar WebP (principal)
        var webpFilename = $"{baseFilename}.webp";
        var webpPath = Path.Combine(uploadDir, webpFilename);
        await System.IO.File.WriteAllBytesAsync(webpPath, optimization.WebpData!);

        // 2. Guardar Thumbnail
        var thumbFilename = $"{baseFilename}_thumb.webp";
        var thumbPath = Path.Combine(uploadDir, thumbFilename);
        await System.IO.File.WriteAllBytesAsync(thumbPath, optimization.ThumbnailData!);

        // 3. Guardar JPEG fallback
        var jpegFilename = $"{baseFilename}.jpg";
        var jpegPath = Path.Combine(uploadDir, jpegFilename);
        await System.IO.File.WriteAllBytesAsync(jpegPath, optimization.JpegData!);

        // URLs relativas
        var webpUrl = $"/uploads/listings/{listingId}/{webpFilename}";
        var thumbUrl = $"/uploads/listings/{listingId}/{thumbFilename}";
        var jpegUrl = $"/uploads/listings/{listingId}/{jpegFilename}";

        // Guardar metadata en BD (solo la imagen principal WebP)
        var image = new ListingImage
        {
            ListingId = listingId,
            Url = webpUrl,
            IsMainInfo = false,
            DisplayOrder = 0
        };
        await _repository.AddAsync(image);

        // Retornar todas las versiones y estadísticas
        return Ok(new { 
            webpUrl,
            thumbUrl,
            jpegUrl,
            optimization = new {
                originalSize = optimization.OriginalSize,
                webpSize = optimization.WebpSize,
                compressionRatio = $"{optimization.CompressionRatio:F1}%",
                dimensions = $"{optimization.OptimizedWidth}x{optimization.OptimizedHeight}",
                thumbnailSize = optimization.ThumbnailSize
            }
        });
    }

    /// <summary>
    /// Obtener información de una imagen sin descargarla
    /// </summary>
    [HttpHead("{listingId}/{filename}")]
    public async Task<IActionResult> GetImageInfo(int listingId, string filename)
    {
        // Seguridad: Solo permitimos el nombre del archivo, no rutas
        string sanitizedFilename = Path.GetFileName(filename);
        string webRootPath = _env.WebRootPath ?? Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
        var imagePath = Path.Combine(webRootPath, "uploads", "listings", listingId.ToString(), sanitizedFilename);

        if (!System.IO.File.Exists(imagePath))
            return NotFound();

        var fileInfo = new FileInfo(imagePath);
        Response.Headers["Content-Length"] = fileInfo.Length.ToString();
        Response.Headers["Content-Type"] = "image/webp";
        
        return Ok();
    }

    /// <summary>
    /// Eliminar imagen y todas sus versiones
    /// </summary>
    [HttpDelete("{imageId}")]
    public async Task<IActionResult> Delete(int imageId)
    {
        var image = await _repository.GetByIdAsync(imageId);
        if (image == null) return NotFound();

        // Extraer información de la URL
        var parts = image.Url.Split('/');
        var listingId = parts[3];
        var filename = Path.GetFileNameWithoutExtension(parts[4]);

        string webRootPath = _env.WebRootPath ?? Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
        var uploadDir = Path.Combine(webRootPath, "uploads", "listings", listingId);

        // Eliminar todas las versiones
        var filesToDelete = new[]
        {
            Path.Combine(uploadDir, $"{filename}.webp"),
            Path.Combine(uploadDir, $"{filename}_thumb.webp"),
            Path.Combine(uploadDir, $"{filename}.jpg")
        };

        foreach (var file in filesToDelete)
        {
            if (System.IO.File.Exists(file))
            {
                System.IO.File.Delete(file);
            }
        }

        // Eliminar de BD
        await _repository.DeleteAsync(imageId);

        return Ok(new { message = "Image and all variants deleted successfully" });
    }
}
