<?php

namespace App\Campaigns\Platforms;

use App\Models\Campaign;

/**
 * What one advertising platform will and will not accept.
 *
 * Every platform disagrees about objectives, bid strategies, placements and
 * minimum spend, and getting a pairing wrong is not a validation error you can
 * reason about from the message: Meta answers an objective/event mismatch with
 * "conversion event unavailable", subcode 2446814.
 *
 * Declaring the rules per platform means the campaign builder never has to know
 * which platform it is building for, and a new platform becomes one class rather
 * than a search for every place a rule was assumed.
 */
interface PlatformRules
{
    /** The key used in config and on the campaign row, for example "meta". */
    public function key(): string;

    /** Human name, for messages shown to the user. */
    public function name(): string;

    /** @return list<string> objectives this platform accepts */
    public function objectives(): array;

    /** @return list<string> bid strategies this platform accepts */
    public function bidStrategies(): array;

    /** @return list<string> placements this platform accepts */
    public function placements(): array;

    /** @return list<string> calls to action this platform accepts */
    public function callsToAction(): array;

    /** Smallest daily budget the platform will take, in whole currency units. */
    public function minimumDailyBudget(): float;

    /** What the platform optimises toward for an objective. */
    public function optimizationGoal(string $objective): ?string;

    /** The conversion event an objective counts, if any. */
    public function conversionEvent(string $objective): ?string;

    /** Whether this objective cannot run without a conversion pixel. */
    public function requiresPixel(string $objective): bool;

    /**
     * Anything else this platform requires that the shared checks cannot know.
     *
     * Returned as reasons phrased for the user, empty when nothing is wrong.
     *
     * @return list<string>
     */
    public function additionalProblems(Campaign $campaign): array;

    /**
     * Fields that can be changed on a live campaign.
     *
     * Everything else needs replacing rather than editing. On Meta an ad's
     * creative is immutable, so changing a headline means a new creative and a
     * new ad rather than an update.
     *
     * @return list<string>
     */
    public function editableAfterPublish(): array;
}
