using JobTrackerApi.Data; using JobTrackerApi.Models; using JobTrackerApi.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace JobTrackerApi.Controllers; [ApiController] [Route("api/ai/usage")] [Authorize(AuthenticationSchemes = "local")] public sealed class AiUsageController : ControllerBase { private readonly UserManager _users; private readonly JobTrackerContext _db; private readonly AiUsageMeter? _usage; public AiUsageController(UserManager users, JobTrackerContext db, AiUsageMeter? usage = null) { _users = users; _db = db; _usage = usage; } public sealed record UsagePeriodDto(int Calls, long InputCharacters, long OutputCharacters, long EstimatedTokens); public sealed record UsageDto(UsagePeriodDto CurrentMonth, UsagePeriodDto AllTime, string Plan, int MonthlyCallLimit, long MonthlyTokenLimit, long StorageUsedBytes, long StorageLimitBytes); [HttpGet] public async Task> Get(CancellationToken cancellationToken) { var user = await _users.GetUserAsync(User); if (user is null) return Unauthorized(); var roles = await _users.GetRolesAsync(user); var entitlements = AccountPlans.ForRoles(roles); var meter = _usage ?? new AiUsageMeter(_db, TimeProvider.System); var currentMonth = ToDto(await meter.CurrentMonthAsync(user.Id, cancellationToken)); return Ok(new UsageDto( currentMonth, ToDto(await meter.AllTimeAsync(user.Id, cancellationToken)), AccountPlans.Name(entitlements), entitlements.MonthlyAiCalls, entitlements.MonthlyAiTokens, await _db.Attachments.Where(x => x.JobApplication.OwnerUserId == user.Id) .SumAsync(x => (long?)x.FileSize, cancellationToken) ?? 0, entitlements.StorageBytes)); } private static UsagePeriodDto ToDto(AiUsageTotals totals) => new(totals.Calls, totals.InputCharacters, totals.OutputCharacters, totals.EstimatedTokens); }