using JobTrackerApi.Models; using JobTrackerApi.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; namespace JobTrackerApi.Controllers; // Phase 5.3 — Application Intelligence. Three read-only endpoints on the application: // timeline (interprets JobEvent), analysis (reads the advert), match (reads the master profile). // // None of them write anything. The AI narrative for analysis and match stays on the existing // /api/jobapplications/{id}/ai routes, which are suggestion-only and versioned by AiInteraction. // docs/architecture/application-workspace.md. [ApiController] [Route("api/jobapplications/{jobId:int}")] [Authorize(AuthenticationSchemes = "local")] public sealed class ApplicationIntelligenceController : ControllerBase { private readonly UserManager _users; private readonly IApplicationTimelineService _timeline; private readonly IApplicationIntelligenceService _intelligence; public ApplicationIntelligenceController( UserManager users, IApplicationTimelineService timeline, IApplicationIntelligenceService intelligence) { _users = users; _timeline = timeline; _intelligence = intelligence; } [HttpGet("timeline")] public async Task> GetTimeline( int jobId, [FromQuery] string? category, [FromQuery] bool milestonesOnly, CancellationToken ct) { var userId = await CurrentUserIdAsync(); if (userId is null) return Unauthorized(); var result = await _timeline.GetAsync(userId, jobId, category, milestonesOnly, ct); return result is null ? NotFound() : Ok(result); } [HttpGet("analysis")] public async Task> GetAnalysis(int jobId, CancellationToken ct) { var userId = await CurrentUserIdAsync(); if (userId is null) return Unauthorized(); var result = await _intelligence.AnalyzeAsync(userId, jobId, ct); return result is null ? NotFound() : Ok(result); } [HttpGet("match")] public async Task> GetMatch(int jobId, CancellationToken ct) { var userId = await CurrentUserIdAsync(); if (userId is null) return Unauthorized(); var result = await _intelligence.MatchAsync(userId, jobId, ct); return result is null ? NotFound() : Ok(result); } private async Task CurrentUserIdAsync() => (await _users.GetUserAsync(User))?.Id; }