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; }
}