using FlatRender.IdentitySvc.Application.Services; using FlatRender.IdentitySvc.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FlatRender.IdentitySvc.Controllers; [ApiController] [Authorize(Roles = "Admin")] public class AdminController(AdminService svc) : ControllerBase { private Guid TenantId => Guid.TryParse(User.FindFirst("tenant_id")?.Value, out var t) ? t : Guid.Parse("00000000-0000-0000-0000-000000000001"); // ── CRM analytics ──────────────────────────────────────────────────────── [HttpGet("v1/admin/crm/analytics")] public async Task Crm([FromQuery] DateTime? start, [FromQuery] DateTime? end) { var s = start ?? DateTime.UtcNow.AddDays(-30); var e = end ?? DateTime.UtcNow; return Ok(await svc.GetCrmAnalyticsAsync(TenantId, s, e)); } // ── Plan statistics ────────────────────────────────────────────────────── [HttpGet("v1/admin/plan-statistics")] public async Task PlanStats() => Ok(await svc.GetPlanStatisticsAsync(TenantId)); // ── OAuth provider config ────────────────────────────────────────────────── [HttpGet("v1/admin/oauth/{provider}")] public async Task GetOAuth(string provider, [FromServices] OAuthService oauth) { var c = await oauth.GetConfigAsync(provider); return Ok(new OAuthConfigResponse(provider, c?.ClientId, c?.RedirectUri, c?.Enabled ?? false, !string.IsNullOrEmpty(c?.ClientSecret))); } [HttpPut("v1/admin/oauth/{provider}")] public async Task PutOAuth(string provider, [FromBody] UpsertOAuthConfigRequest req, [FromServices] OAuthService oauth) { var c = await oauth.UpsertConfigAsync(provider, req.ClientId, req.ClientSecret, req.RedirectUri, req.Enabled); return Ok(new OAuthConfigResponse(provider, c.ClientId, c.RedirectUri, c.Enabled, !string.IsNullOrEmpty(c.ClientSecret))); } // ── CRM notes / tags ─────────────────────────────────────────────────────── [HttpGet("v1/users/{userId:guid}/crm")] public async Task GetCrm(Guid userId) => Ok(await svc.GetUserCrmAsync(userId)); [HttpPut("v1/users/{userId:guid}/crm")] public async Task PutCrm(Guid userId, [FromBody] UpsertUserCrmRequest req) => Ok(await svc.UpsertUserCrmAsync(userId, req)); // ── Power-actions ────────────────────────────────────────────────────────── [HttpPost("v1/users/{userId:guid}/balance")] public async Task Balance(Guid userId, [FromBody] SetBalanceRequest req) { await svc.SetBalanceAsync(userId, req.AmountMinor, req.Add); return Ok(new { ok = true }); } [HttpPost("v1/users/{userId:guid}/password")] public async Task Password(Guid userId, [FromBody] ResetPasswordRequest req) { await svc.ResetPasswordAsync(userId, req.NewPassword); return Ok(new { ok = true }); } [HttpPost("v1/users/{userId:guid}/charge")] public async Task Charge(Guid userId, [FromBody] AddChargeRequest req) { await svc.AddChargeAsync(userId, req.Seconds, req.RenderCount); return Ok(new { ok = true }); } [HttpPost("v1/users/{userId:guid}/moderator")] public async Task Moderator(Guid userId, [FromBody] SetFlagRequest req) { await svc.SetModeratorAsync(userId, req.Enabled); return Ok(new { ok = true }); } [HttpPost("v1/users/{userId:guid}/grant-plan")] public async Task GrantPlan(Guid userId, [FromBody] GrantPlanDaysRequest req) { try { await svc.GrantPlanDaysAsync(userId, req.PlanId, req.Days); return Ok(new { ok = true }); } catch (KeyNotFoundException ex) { return BadRequest(new { error = new { message = ex.Message } }); } } }