using JobTrackerApi.Models;
using JobTrackerApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;

namespace JobTrackerApi.Controllers;

// Anonymous read-only surface for public CVs: /cv/{slug} in the SPA fetches this. Only variants the
// owner has explicitly toggled public are served; noindex by default. docs/architecture/cv-builder.md.
[ApiController]
[Route("api/public-cv")]
[AllowAnonymous]
public sealed class PublicCvController : ControllerBase
{
    private readonly UserManager<ApplicationUser> _users;
    private readonly ICvVariantService _variants;
    private readonly ICvPdfExporter _pdf;

    public PublicCvController(UserManager<ApplicationUser> users, ICvVariantService variants, ICvPdfExporter pdf)
    {
        _users = users;
        _variants = variants;
        _pdf = pdf;
    }

    [HttpGet("{slug}")]
    public async Task<IActionResult> Get(string slug, CancellationToken ct)
    {
        var ownerId = await _variants.GetPublicOwnerAsync(slug, ct);
        if (ownerId is null) return NotFound();

        var owner = await _users.FindByIdAsync(ownerId);
        var person = Person(owner);
        var result = await _variants.RenderPublicAsync(slug, person, ct);
        if (result is null) return NotFound();

        Response.Headers["X-Robots-Tag"] = "noindex, nofollow";
        return Ok(new { html = result.Value.render.Html, name = person.FallbackName });
    }

    [HttpGet("{slug}/pdf")]
    [EnableRateLimiting("public-pdf")]
    public async Task<IActionResult> DownloadPdf(string slug, CancellationToken ct)
    {
        var ownerId = await _variants.GetPublicOwnerAsync(slug, ct);
        if (ownerId is null) return NotFound();

        var person = Person(await _users.FindByIdAsync(ownerId));
        var result = await _variants.RenderPublicAsync(slug, person, ct);
        if (result is null) return NotFound();

        var render = result.Value.render;
        var artifact = await _pdf.ExportAsync(ownerId, new TailoredCvRenderResult(render.ThemeId, render.SuggestedFileName, render.Html), ct);
        return File(artifact.Bytes, "application/pdf", artifact.FileName);
    }

    private static CvRenderPerson Person(ApplicationUser? user)
    {
        if (user is null) return new CvRenderPerson("Candidate", null);
        var name = string.Join(" ", new[] { user.FirstName?.Trim(), user.LastName?.Trim() }.Where(x => !string.IsNullOrWhiteSpace(x)));
        if (string.IsNullOrWhiteSpace(name)) name = user.DisplayName?.Trim();
        if (string.IsNullOrWhiteSpace(name)) name = user.UserName?.Trim();
        if (string.IsNullOrWhiteSpace(name)) name = "Candidate";
        return new CvRenderPerson(name!, AvatarStorage.Resolve(user.AvatarImageDataUrl));
    }
}
