using FlatRender.IdentitySvc.Application.Services.Interfaces; using FlatRender.IdentitySvc.Models.Requests; using FlatRender.IdentitySvc.Models.Responses; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FlatRender.IdentitySvc.Controllers; [ApiController] [Route("v1")] [Authorize] public class PlansController(IPlanService planService) : ControllerBase { [AllowAnonymous] [HttpGet("plans")] [ProducesResponseType(typeof(object), 200)] public async Task List([FromQuery] string? scope) { var plans = await planService.ListAsync(GetTenantIdOrNull(), scope); return Ok(new { data = plans }); } [AllowAnonymous] [HttpGet("plans/{planId:guid}")] [ProducesResponseType(typeof(PlanResponse), 200)] public async Task GetById(Guid planId) => Ok(await planService.GetByIdAsync(planId)); [HttpGet("users/me/plan")] [ProducesResponseType(typeof(UserPlanResponse), 200)] public async Task GetCurrentPlan() => Ok(await planService.GetCurrentPlanAsync(GetUserId())); [HttpPost("users/me/plan/purchase")] [ProducesResponseType(typeof(PurchasePlanResponse), 200)] public async Task Purchase([FromBody] PurchasePlanRequest request) { var result = await planService.PurchasePlanAsync(GetUserId(), GetTenantId(), request); return Ok(result); } /// /// Cancel the current active subscription. The plan stays active until its /// expiry date but will not auto-renew. Returns 404 when no active plan exists. /// [HttpPost("users/me/plan/cancel")] [ProducesResponseType(204)] [ProducesResponseType(404)] public async Task Cancel() { try { await planService.CancelPlanAsync(GetUserId()); return NoContent(); } catch (KeyNotFoundException ex) { return NotFound(new { error = ex.Message }); } } private Guid GetUserId() => Guid.Parse(User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? User.FindFirst("sub")?.Value ?? throw new UnauthorizedAccessException()); private Guid GetTenantId() => Guid.Parse(User.FindFirst("tenant_id")?.Value ?? throw new UnauthorizedAccessException()); private Guid? GetTenantIdOrNull() => User.FindFirst("tenant_id")?.Value is { } t && Guid.TryParse(t, out var id) ? id : null; }