Files
AdPlatform-Server/IntelligenceApi/Controllers/SpendDistributionController.cs
2026-03-14 13:50:09 -07:00

68 lines
2.3 KiB
C#

using IntelligenceApi.Engines;
using IntelligenceApi.Models;
using Microsoft.AspNetCore.Mvc;
namespace IntelligenceApi.Controllers;
/// <summary>
/// Spend distribution endpoint — the single public surface of IntelligenceApi.
///
/// Called exclusively by the Gateway (never directly by the client portal).
/// The Gateway injects clientCategory from ClientContext before forwarding.
///
/// POST /api/spend-distribution
/// </summary>
[ApiController]
[Route("api/spend-distribution")]
public sealed class SpendDistributionController : ControllerBase
{
private readonly EngineRouter _router;
private readonly ILogger<SpendDistributionController> _log;
public SpendDistributionController(EngineRouter router, ILogger<SpendDistributionController> log)
{
_router = router;
_log = log;
}
/// <summary>
/// Generate a spend distribution recommendation.
/// clientCategory in the request body determines which engine runs.
/// </summary>
[HttpPost]
public async Task<IActionResult> Recommend(
[FromBody] SpendDistributionRequest? request,
CancellationToken ct)
{
if (request == null)
return BadRequest(new { ok = false, error = "Request body required" });
if (request.MonthlyBudget <= 0)
return BadRequest(new { ok = false, error = "monthlyBudget must be greater than zero" });
if (request.Keywords.Count == 0)
return BadRequest(new { ok = false, error = "At least one keyword is required" });
_log.LogInformation(
"[SpendDistribution] Request | Category={Category} Budget={Budget} Objective={Obj}",
request.ClientCategory, request.MonthlyBudget, request.Objective);
try
{
var engine = _router.Resolve(request.ClientCategory);
var response = await engine.RecommendAsync(request, ct);
_log.LogInformation(
"[SpendDistribution] OK | Engine={Engine} Channels={N}",
response.Metadata.Engine, response.Channels.Count);
return Ok(response);
}
catch (Exception ex)
{
_log.LogError(ex, "[SpendDistribution] Unhandled error");
return StatusCode(500, new { ok = false, error = "Intelligence service error" });
}
}
}