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

namespace JobTrackerApi.Controllers;

// Phase 5.4 — Application Assets. Connects existing career outputs to one application.
//
// Deliberately thin: CV variant CRUD, preview, PDF export, themes and version history all stay on
// /api/cv (CvVariantController), and documents stay on /api/attachments. These routes only cover what
// is genuinely application-scoped — which variant this application uses, what to tailor, and the
// cover letter with its history. Every route is tenant-scoped and returns 404 for another user's
// application. docs/architecture/application-workspace.md.
[ApiController]
[Route("api/jobapplications/{jobId:int}")]
[Authorize(AuthenticationSchemes = "local")]
public sealed class ApplicationAssetsController : ControllerBase
{
    public sealed record AttachVariantRequest(int? VariantId);
    public sealed record SaveCoverLetterRequest(string? Text, string? Source, string? AiAction);

    private readonly UserManager<ApplicationUser> _users;
    private readonly IApplicationAssetsService _assets;

    public ApplicationAssetsController(UserManager<ApplicationUser> users, IApplicationAssetsService assets)
    {
        _users = users;
        _assets = assets;
    }

    [HttpGet("cv")]
    public async Task<ActionResult<ApplicationCvDto>> GetCv(int jobId, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.GetCvAsync(userId, jobId, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpPut("cv")]
    public async Task<ActionResult<ApplicationCvDto>> AttachVariant(int jobId, [FromBody] AttachVariantRequest request, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.AttachVariantAsync(userId, jobId, request?.VariantId, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpGet("tailoring")]
    public async Task<ActionResult<TailoringPlanDto>> GetTailoring(int jobId, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.GetTailoringPlanAsync(userId, jobId, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpGet("cover-letter")]
    public async Task<ActionResult<CoverLetterDto>> GetCoverLetter(int jobId, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.GetCoverLetterAsync(userId, jobId, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpPut("cover-letter")]
    public async Task<ActionResult<CoverLetterDto>> SaveCoverLetter(int jobId, [FromBody] SaveCoverLetterRequest request, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.SaveCoverLetterAsync(
            userId, jobId, request?.Text, request?.Source ?? CoverLetterSources.Manual, request?.AiAction, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpPost("cover-letter/versions/{version:int}/restore")]
    public async Task<ActionResult<CoverLetterDto>> RestoreCoverLetter(int jobId, int version, CancellationToken ct)
    {
        var userId = await CurrentUserIdAsync();
        if (userId is null) return Unauthorized();
        var result = await _assets.RestoreCoverLetterAsync(userId, jobId, version, ct);
        return result is null ? NotFound() : Ok(result);
    }

    private async Task<string?> CurrentUserIdAsync() => (await _users.GetUserAsync(User))?.Id;
}
