using Management.Data; using Management.Security; using Microsoft.AspNetCore.Mvc; using System.Text.Json; namespace Management.Controllers.Admin; /// /// Admin endpoints for objective-to-channel mapping management. /// Table: dbo.tbObjectiveMapping /// Maps platform objectives to provider-specific objectives with capability flags. /// /// ENDPOINTS: /// GET /api/admin/objectives - List mappings (filterable) /// GET /api/admin/objectives/{id} - Get mapping /// POST /api/admin/objectives - Create mapping /// PUT /api/admin/objectives/{id} - Update mapping /// DELETE /api/admin/objectives/{id} - Delete mapping /// [ApiController] [Route("api/admin/objectives")] public sealed class AdminObjectiveMappingController : AdminControllerBase { public AdminObjectiveMappingController(SqlService sql, ClientContext client, ILogger log) : base(sql, client, log) { } [HttpPost("list")] public Task List([FromBody] JsonElement body, CancellationToken ct) => CallProc("spAdminObjectiveMapping", "list", body.ToString(), ct); [HttpGet("{mappingId:int}")] public Task Get(int mappingId, CancellationToken ct) => CallProc("spAdminObjectiveMapping", "get", new { mappingId }, ct); [HttpPost] public Task Create([FromBody] CreateMappingRequest request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request?.ChannelType)) return Task.FromResult(ValidationError("channelType is required")); if (string.IsNullOrWhiteSpace(request?.PlatformObjective)) return Task.FromResult(ValidationError("platformObjective is required")); if (string.IsNullOrWhiteSpace(request?.ProviderObjective)) return Task.FromResult(ValidationError("providerObjective is required")); if (string.IsNullOrWhiteSpace(request?.ProviderObjectiveLabel)) return Task.FromResult(ValidationError("providerObjectiveLabel is required")); Logger.LogWarning("[Admin] CreateObjectiveMapping | {Objective} → {Channel}/{Provider} | By={User}", request.PlatformObjective, request.ChannelType, request.ProviderObjective, Client.Email); return CallProc("spAdminObjectiveMapping", "create", new { channelType = request.ChannelType.Trim(), platformObjective = request.PlatformObjective.Trim(), providerObjective = request.ProviderObjective.Trim(), providerObjectiveLabel = request.ProviderObjectiveLabel.Trim(), supportsObjectiveChange = request.SupportsObjectiveChange ?? false, supportsBudgetChange = request.SupportsBudgetChange ?? true, supportsTargetingChange = request.SupportsTargetingChange ?? true, supportsStatusToggle = request.SupportsStatusToggle ?? true, notes = request.Notes?.Trim() }, ct); } [HttpPut("{mappingId:int}")] public Task Update(int mappingId, [FromBody] UpdateMappingRequest request, CancellationToken ct) { Logger.LogWarning("[Admin] UpdateObjectiveMapping | Id={Id} | By={User}", mappingId, Client.Email); return CallProc("spAdminObjectiveMapping", "update", new { mappingId, channelType = request?.ChannelType?.Trim(), platformObjective = request?.PlatformObjective?.Trim(), providerObjective = request?.ProviderObjective?.Trim(), providerObjectiveLabel = request?.ProviderObjectiveLabel?.Trim(), supportsObjectiveChange = request?.SupportsObjectiveChange, supportsBudgetChange = request?.SupportsBudgetChange, supportsTargetingChange = request?.SupportsTargetingChange, supportsStatusToggle = request?.SupportsStatusToggle, notes = request?.Notes?.Trim(), isActive = request?.IsActive }, ct); } [HttpDelete("{mappingId:int}")] public Task Delete(int mappingId, CancellationToken ct) { Logger.LogWarning("[Admin] DeleteObjectiveMapping | Id={Id} | By={User}", mappingId, Client.Email); return CallProc("spAdminObjectiveMapping", "delete", new { mappingId }, ct); } } // DTOs public sealed class CreateMappingRequest { public string? ChannelType { get; set; } public string? PlatformObjective { get; set; } public string? ProviderObjective { get; set; } public string? ProviderObjectiveLabel { get; set; } public bool? SupportsObjectiveChange { get; set; } public bool? SupportsBudgetChange { get; set; } public bool? SupportsTargetingChange { get; set; } public bool? SupportsStatusToggle { get; set; } public string? Notes { get; set; } } public sealed class UpdateMappingRequest { public string? ChannelType { get; set; } public string? PlatformObjective { get; set; } public string? ProviderObjective { get; set; } public string? ProviderObjectiveLabel { get; set; } public bool? SupportsObjectiveChange { get; set; } public bool? SupportsBudgetChange { get; set; } public bool? SupportsTargetingChange { get; set; } public bool? SupportsStatusToggle { get; set; } public string? Notes { get; set; } public bool? IsActive { get; set; } }