using MailPrint.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.ComponentModel.DataAnnotations;

namespace MailPrint.Controllers;

[ApiController]
[Route("api/[controller]")]
public class PrintController : ControllerBase
{
    private readonly PrintService _printService;
    private readonly MailPrintOptions _options;
    private readonly ILogger<PrintController> _logger;

    public PrintController(PrintService printService, IOptions<MailPrintOptions> options, ILogger<PrintController> logger)
    {
        _printService = printService;
        _options = options.Value;
        _logger = logger;
    }

    /// <summary>
    /// PDF hochladen und drucken.
    /// POST /api/print/upload
    /// Form-Data: file, printer (opt), paperSource (opt), copies (opt)
    /// </summary>
    [HttpPost("upload")]
    [Consumes("multipart/form-data")]
    public async Task<IActionResult> PrintUpload(
        IFormFile file,
        [FromForm] string? printer = null,
        [FromForm] string? paperSource = null,
        [FromForm] int copies = 0)
    {
        if (file is null || file.Length == 0)
            return BadRequest(new { error = "Keine Datei." });

        var ext = Path.GetExtension(file.FileName).ToLower();
        if (!_options.AllowedExtensions.Contains(ext))
            return BadRequest(new { error = $"Dateityp '{ext}' nicht erlaubt." });

        Directory.CreateDirectory(_options.TempDirectory);
        var tempFile = Path.Combine(_options.TempDirectory, $"{Guid.NewGuid()}{ext}");

        try
        {
            await using (var fs = System.IO.File.Create(tempFile))
                await file.CopyToAsync(fs);

            _printService.PrintPdf(new PrintJob
            {
                FilePath = tempFile,
                MailSubject = file.FileName,
                MailFrom = "WebAPI",
                PrinterOverride = printer,
                PaperSourceOverride = paperSource,
                CopiesOverride = copies > 0 ? copies : null
            });

            return Ok(new { success = true, file = file.FileName, printer, paperSource });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "WebAPI Druckfehler: {File}", file.FileName);
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// PDF per URL drucken.
    /// POST /api/print/url
    /// </summary>
    [HttpPost("url")]
    public async Task<IActionResult> PrintUrl([FromBody] PrintUrlRequest request)
    {
        if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri))
            return BadRequest(new { error = "Ungültige URL." });

        Directory.CreateDirectory(_options.TempDirectory);
        var tempFile = Path.Combine(_options.TempDirectory, $"{Guid.NewGuid()}.pdf");

        try
        {
            using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
            await System.IO.File.WriteAllBytesAsync(tempFile, await http.GetByteArrayAsync(uri));

            _printService.PrintPdf(new PrintJob
            {
                FilePath = tempFile,
                MailSubject = uri.Segments.LastOrDefault() ?? "download.pdf",
                MailFrom = "WebAPI/URL",
                PrinterOverride = request.Printer,
                PaperSourceOverride = request.PaperSource,
                CopiesOverride = request.Copies > 0 ? request.Copies : null
            });

            return Ok(new { success = true, url = request.Url, printer = request.Printer, paperSource = request.PaperSource });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "WebAPI URL-Druckfehler: {Url}", request.Url);
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Alle Drucker mit Papierfächern.
    /// GET /api/print/printers
    /// </summary>
    [HttpGet("printers")]
    public IActionResult GetPrinters()
    {
        var infos = _printService.GetPrinterInfos();
        var defaultPrinter = _options.PrinterProfiles.FirstOrDefault()?.PrinterName
            ?? infos.FirstOrDefault()?.Name;
        return Ok(new { defaultPrinter, profiles = _options.PrinterProfiles, printers = infos });
    }

    [HttpGet("health")]
    public IActionResult Health() =>
        Ok(new { status = "ok", service = "MailPrint", timestamp = DateTime.UtcNow });
}

public class PrintUrlRequest
{
    [Required] public string Url { get; set; } = "";
    public string? Printer { get; set; }
    public string? PaperSource { get; set; }
    public int Copies { get; set; } = 0;
}
