<?php

namespace App\Campaigns;

use App\Models\Campaign;

/**
 * The most this product will let one campaign spend a day, in the currency the
 * ad account actually bills in.
 *
 * One number compared against whatever an account charges in is not a ceiling:
 * the same 20 stopped a 20 dollar campaign and a 20 rupee one, and on a yen
 * account it blocked every campaign worth running.
 *
 * Configured per currency rather than converted, because an exchange rate that
 * moves would quietly move a spending limit with it.
 *
 * Lives here rather than on the publish gate because two places enforce it and
 * they disagreed: the gate had the currency-aware version while the budget tool
 * still used the base-currency number, so the tool refused amounts the gate
 * would have allowed.
 */
class BudgetCeiling
{
    /** Null when this account's currency has no configured ceiling, which fails closed. */
    public static function for(Campaign $campaign): ?float
    {
        $base = (string) config('platforms.guardrails.budget_ceiling_currency', 'USD');
        $currency = strtoupper((string) ($campaign->currency ?: $base));

        if ($currency === strtoupper($base)) {
            return (float) config('platforms.guardrails.max_daily_budget');
        }

        return config('platforms.guardrails.max_daily_budget_by_currency')[$currency] ?? null;
    }

    /**
     * Why the campaign cannot proceed without one, phrased for whoever reads it.
     *
     * Shared so the gate and the tool say the same thing; being refused by one
     * in different words from the other is how a buyer concludes the product is
     * broken rather than unconfigured.
     */
    public static function missingReason(Campaign $campaign): string
    {
        return sprintf(
            'no budget ceiling is configured for %s, which is what this ad account bills in. '
            .'Set PLATFORM_MAX_DAILY_BUDGET_BY_CURRENCY before publishing to it',
            $campaign->currency,
        );
    }
}
