<?php

use App\Services\AI\ApifyMetaAdLibraryProvider;
use App\Services\AI\GeminiVeoVertexVideoProvider;
use App\Services\AI\GeminiVeoVideoAvatarProvider;
use App\Services\AI\PuppeteerMetaAdLibraryProvider;
use App\Services\Platforms\GoogleAdapter;
use App\Services\Platforms\LinkedInAdapter;
use App\Services\Platforms\TaboolaAdapter;
use App\Services\Platforms\TikTokAdapter;

return [

    /*
    |--------------------------------------------------------------------------
    | Creative Disk
    |--------------------------------------------------------------------------
    |
    | Where generated creatives are written. Named here because the assets they
    | become record which disk holds them, and the upload to a platform reads
    | the file back from it. Uploads from the chat use the default disk instead.
    |
    */

    'disk' => env('CREATIVE_DISK', 'public'),

    // Used only to burn spoken captions onto a finished mp4. Empty uses PATH, then known install locations.
    'ffmpeg_binary' => env('FFMPEG_BINARY'),

    /*
    |--------------------------------------------------------------------------
    | Video Avatar Provider
    |--------------------------------------------------------------------------
    |
    | Gemini Veo handles 4 and 6 second clips. Vertex Veo handles the 8-second
    | clip and native extensions for 15 and 30-second requests. The retired
    | Sora Videos API is not routed.
    | VIDEO_ENGINE picks the engine for new videos. higgsfield-seedance is the
    | default and is never selected by duration. Set veo to use Vertex for
    | 8s, 15s, and 30s. HF_VIDEO_MODEL picks wan-3.0 or seedance-2.5.
    |
    | spoken_words_per_second bounds dialogue to the requested clip duration.
    |
    */

    'video_provider' => GeminiVeoVideoAvatarProvider::class,

    // New videos use this engine. higgsfield-seedance is the default. veo or vertex uses Veo.
    'video_engine' => env('VIDEO_ENGINE', 'higgsfield-seedance'),

    // Durations rendered on Vertex AI. The value is the number of native "extend video"
    // calls after the 8s base clip (Google extends server-side, no ffmpeg/local stitching).
    // Each extend adds a fixed 7s. 8s is the base clip alone. The 30s preset uses three
    // extensions and produces a 29s asset; the provider reports that actual duration.
    // Keyed by requested duration => number of extend calls after the base clip.
    'vertex_extend_durations' => [8 => 0, 15 => 1, 30 => 3],
    'video_provider_vertex_extend' => GeminiVeoVertexVideoProvider::class,

    'gemini_veo' => [
        // veo-3.0-generate-001 returns 404 for predictLongRunning on this API key/version;
        // confirmed available via models.list: veo-3.1-generate-preview, veo-3.1-generate-preview.
        'model' => env('GEMINI_VEO_MODEL', 'veo-3.1-generate-preview'),
        'poll_interval_seconds' => env('GEMINI_VEO_POLL_INTERVAL', 10),
        'max_poll_attempts' => env('GEMINI_VEO_MAX_POLL_ATTEMPTS', 30),
    ],

    // Vertex AI (not the Gemini Developer API) is required for the native "extend video" call —
    // authenticated via a service account (see App\Services\Google\GoogleServiceAccountTokenProvider
    // and config('services.vertex_ai')), not GEMINI_API_KEY.
    'gemini_veo_vertex' => [
        // Vertex's Veo model IDs don't carry the "-preview" suffix used by the Developer API.
        'model' => env('GEMINI_VEO_VERTEX_MODEL', 'veo-3.1-generate-001'),
        'poll_interval_seconds' => env('GEMINI_VEO_VERTEX_POLL_INTERVAL', 10),
        'max_poll_attempts' => env('GEMINI_VEO_VERTEX_MAX_POLL_ATTEMPTS', 30),
    ],

    // Higgsfield text-to-video. Used when VIDEO_ENGINE is higgsfield-seedance.
    // Switch the model with HF_VIDEO_MODEL=wan-3.0 or seedance-2.5. Credentials stay server-side.
    'higgsfield_model' => env('HF_VIDEO_MODEL', 'wan-3.0'),
    'higgsfield_resolution' => env('HF_VIDEO_RESOLUTION'),
    'higgsfield_models' => [
        'wan-3.0' => [
            'label' => 'Wan',
            'endpoint' => 'alibaba/wan-3.0/text-to-video',
            'model' => 'alibaba/wan-3.0',
            'resolution' => '480p',
        ],
        'seedance-2.5' => [
            'label' => 'Seedance',
            'endpoint' => 'bytedance/seedance-2.5/text-to-video',
            'model' => 'bytedance/seedance-2.5',
            'resolution' => '480p',
        ],
    ],
    'higgsfield_seedance' => [
        'key_id' => env('HF_API_KEY_ID'),
        'key_secret' => env('HF_API_KEY_SECRET'),
        'base_url' => env('HF_API_BASE_URL', 'https://api.higgsfield.ai'),
        'poll_interval_seconds' => env('HF_SEEDANCE_POLL_INTERVAL', 10),
        'max_poll_attempts' => env('HF_SEEDANCE_MAX_POLL_ATTEMPTS', 150),
    ],

    // Legacy adapter settings retained for historical tests; production routing never selects it.
    'openai_sora' => [
        // sora-2: reverted from sora-2-pro (2026-09-11) — this API key isn't provisioned
        // for the pro tier and render requests failed with "Incorrect API key provided".
        'model' => env('OPENAI_SORA_MODEL', 'sora-2'),
        'poll_interval_seconds' => env('OPENAI_SORA_POLL_INTERVAL', 10),
        // 60 * 10s = 600s per render step (base clip, then extension) — extensions are a full
        // new render pass and routinely take longer than the base clip's 300s used to allow,
        // which was silently truncating a requested 30s video down to its 12s base clip (see
        // RenderVideoCreativeJob's 900s job timeout, which comfortably covers base + extension).
        'max_poll_attempts' => env('OPENAI_SORA_MAX_POLL_ATTEMPTS', 60),
    ],

    /*
    |--------------------------------------------------------------------------
    | Competitor Ad Provider
    |--------------------------------------------------------------------------
    |
    | Swap this class to choose how the wizard searches Meta's Ad Library:
    | - ApifyMetaAdLibraryProvider: Apify actor (needs APIFY_TOKEN)
    | - MetaAdLibraryProvider: official Graph /ads_archive
    | - PuppeteerMetaAdLibraryProvider: local browser scrape of the Ad Library URL
    |
    | Puppeteer Ad Library scraping is isolated from catalog listing scraping
    | (config/scraping.php and scripts/scraping/*).
    |
    */

    // 'competitor_ad_provider' => ApifyMetaAdLibraryProvider::class,
    // 'competitor_ad_provider' => \App\Services\AI\MetaAdLibraryProvider::class,
    'competitor_ad_provider' => PuppeteerMetaAdLibraryProvider::class,

    'puppeteer_ad_library' => [
        'enabled' => env('AD_LIBRARY_PUPPETEER_ENABLED', true),
        'node_binary' => env('AD_LIBRARY_NODE_BINARY', 'node'),
        'script' => env('AD_LIBRARY_PUPPETEER_SCRIPT', 'scripts/ad-library/scrape-ad-library.js'),
        'timeout_seconds' => (int) env('AD_LIBRARY_PUPPETEER_TIMEOUT', 180),
        'headless' => env('AD_LIBRARY_PUPPETEER_HEADLESS', 'true'),
        'max_ads' => (int) env('AD_LIBRARY_PUPPETEER_MAX_ADS', 20),
    ],

    /*
    | Display name => ISO 3166-1 alpha-2. Used by the competitor-ad search
    | country filter; Meta's ads_archive requires ad_reached_countries.
    */
    'competitor_ad_countries' => [
        'United States' => 'US',
        'United Kingdom' => 'GB',
        'Canada' => 'CA',
        'Australia' => 'AU',
        'India' => 'IN',
        'United Arab Emirates' => 'AE',
        'Argentina' => 'AR',
        'Austria' => 'AT',
        'Belgium' => 'BE',
        'Bangladesh' => 'BD',
        'Brazil' => 'BR',
        'Bulgaria' => 'BG',
        'Chile' => 'CL',
        'China' => 'CN',
        'Colombia' => 'CO',
        'Croatia' => 'HR',
        'Czechia' => 'CZ',
        'Denmark' => 'DK',
        'Egypt' => 'EG',
        'Finland' => 'FI',
        'France' => 'FR',
        'Germany' => 'DE',
        'Greece' => 'GR',
        'Hong Kong' => 'HK',
        'Hungary' => 'HU',
        'Indonesia' => 'ID',
        'Ireland' => 'IE',
        'Israel' => 'IL',
        'Italy' => 'IT',
        'Japan' => 'JP',
        'Kenya' => 'KE',
        'South Korea' => 'KR',
        'Malaysia' => 'MY',
        'Mexico' => 'MX',
        'Netherlands' => 'NL',
        'New Zealand' => 'NZ',
        'Nigeria' => 'NG',
        'Norway' => 'NO',
        'Pakistan' => 'PK',
        'Peru' => 'PE',
        'Philippines' => 'PH',
        'Poland' => 'PL',
        'Portugal' => 'PT',
        'Romania' => 'RO',
        'Russia' => 'RU',
        'Saudi Arabia' => 'SA',
        'Singapore' => 'SG',
        'South Africa' => 'ZA',
        'Spain' => 'ES',
        'Sweden' => 'SE',
        'Switzerland' => 'CH',
        'Taiwan' => 'TW',
        'Thailand' => 'TH',
        'Turkey' => 'TR',
        'Ukraine' => 'UA',
        'Vietnam' => 'VN',
    ],

    'spoken_words_per_second' => (float) env('CREATIVE_SPOKEN_WORDS_PER_SECOND', 2.2),

    // Wan speaks faster than Veo. Budget the line for the clip minus a silent product second.
    'higgsfield_spoken_words_per_second' => (float) env('HF_SPOKEN_WORDS_PER_SECOND', 2.7),

    /*
    |--------------------------------------------------------------------------
    | URL Brief Reference Images
    |--------------------------------------------------------------------------
    |
    | When a brief is resolved from a product/landing page URL, the raw HTML is
    | scanned for real product photos (og:image/twitter:image + inline <img> tags)
    | before it's stripped down to plain text for the AI prompt — the stripped text
    | never contains image URLs, so without this the "images" field was effectively
    | the AI guessing/hallucinating from prose alone. If the page doesn't look like
    | a single product with clear photos (e.g. a general site/portal), a full-page
    | screenshot is captured instead via Microlink's public endpoint — a plain HTTP
    | call, no headless browser install required (this box has no sudo access).
    |
    */

    'url_brief' => [
        'capture_reference_images' => env('CREATIVE_URL_BRIEF_CAPTURE_IMAGES', true),
        'screenshot_enabled' => env('CREATIVE_URL_BRIEF_SCREENSHOT_ENABLED', true),
        'screenshot_endpoint' => env('CREATIVE_URL_BRIEF_SCREENSHOT_ENDPOINT', 'https://api.microlink.io'),
    ],

    /*
    |--------------------------------------------------------------------------
    | Platform Adapters
    |--------------------------------------------------------------------------
    |
    | Maps a campaign's `platform` value to the adapter class that implements
    | App\Contracts\PlatformAdapter for it. Platforms without a real
    | integration yet resolve to an UnimplementedPlatformAdapter subclass.
    |
    */

    'platform_adapters' => [
        // No Meta entry on purpose. MetaAdapter used to sit here and published
        // by setting a campaign ACTIVE over a bare Http call, so it reached
        // none of the guards every other Meta write goes through: no kill
        // switch, no allowed-account check, no call budget, no audit row. It
        // was unreachable - nothing calls PlatformAdapterFactory - but it was
        // wired here, so it was one call away from being live.
        //
        // Meta publishes through MetaPublisher, which goes Meta -> GraphApi ->
        // CallLogger and is guarded at every step. Asking the factory for meta
        // now fails loudly rather than handing back the ungated path.
        'google' => GoogleAdapter::class,
        'tiktok' => TikTokAdapter::class,
        'taboola' => TaboolaAdapter::class,
        'linkedin' => LinkedInAdapter::class,
    ],

];
