namespace IntelligenceApi.Models;
// ════════════════════════════════════════════════
// Request: Gateway → IntelligenceApi
// Gateway injects clientCategory from ClientContext
// before forwarding the wizard's forecast request.
// ════════════════════════════════════════════════
public sealed class SpendDistributionRequest
{
///
/// Client category — the primary engine selector.
/// Values: General | Franchisee | Franchisor | FoodFranchisee | etc.
/// Injected by the Gateway from ClientContext.ClientCategory.
///
public string ClientCategory { get; set; } = "General";
/// Advertising objective: awareness, traffic, leads, sales
public string Objective { get; set; } = "traffic";
/// Business category from wizard Step 1 (industry)
public string? BusinessCategory { get; set; }
/// Keywords from URL analysis
public List Keywords { get; set; } = new();
/// Geo targeting from audience step
public GeoTargeting? GeoTargeting { get; set; }
/// Audience parameters
public AudienceParams? Audience { get; set; }
/// Monthly budget in whole dollars
public decimal MonthlyBudget { get; set; }
/// Channels to estimate
public List? Channels { get; set; }
///
/// Provider base URLs forwarded from Gateway config.
/// Allows engines to call providers without needing their own config.
///
public Dictionary? ProviderUrls { get; set; }
/// Internal API keys forwarded from Gateway config.
public Dictionary? InternalKeys { get; set; }
}
public sealed class GeoTargeting
{
public List? ZipCodes { get; set; }
public double? RadiusMiles { get; set; }
public List? GeoTargetIds { get; set; }
}
public sealed class AudienceParams
{
public int? AgeMin { get; set; }
public int? AgeMax { get; set; }
public List? Genders { get; set; }
public List? Interests { get; set; }
}
// ════════════════════════════════════════════════
// Response: IntelligenceApi → Gateway → Client
// Identical shape to ChannelForecastResponse in
// the Gateway so no client changes are needed.
// ════════════════════════════════════════════════
public sealed class SpendDistributionResponse
{
public bool Ok { get; set; } = true;
public string Objective { get; set; } = string.Empty;
public decimal TotalBudget { get; set; }
public List Channels { get; set; } = new();
public DistributionRecommendation? Recommendation { get; set; }
public DistributionMeta Metadata { get; set; } = new();
}
public sealed class ChannelAllocation
{
public string Provider { get; set; } = string.Empty;
public int AllocationPercent { get; set; }
public decimal AllocatedBudget { get; set; }
public AllocationMetrics Estimates { get; set; } = new();
public double EfficiencyScore { get; set; }
public string StrengthLabel { get; set; } = string.Empty;
public string Confidence { get; set; } = "none";
public string DataSource { get; set; } = "none";
}
public sealed class AllocationMetrics
{
public double Impressions { get; set; }
public double? Reach { get; set; }
public double Clicks { get; set; }
public double Conversions { get; set; }
public decimal AvgCpc { get; set; }
public decimal AvgCpm { get; set; }
public decimal? EstimatedCpa { get; set; }
public double Ctr { get; set; }
}
public sealed class DistributionRecommendation
{
public string Summary { get; set; } = string.Empty;
public List Highlights { get; set; } = new();
}
public sealed class DistributionMeta
{
public DateTimeOffset GeneratedAt { get; set; } = DateTimeOffset.UtcNow;
public string ForecastPeriod { get; set; } = "30 days";
/// Which engine handled this request — useful for debugging and billing.
public string Engine { get; set; } = "General";
}