<?php

namespace App\Campaigns\Targeting;

use App\Models\GoogleAdsConnection;
use App\Services\GoogleAdsService;
use App\Services\LinkedIn\LinkedInRestApi;
use App\Services\Meta\GraphApi;
use RuntimeException;

/** Read-only provider lookups for country targeting identifiers. */
class CountryLookup
{
    public function __construct(
        private readonly GoogleAdsService $google,
        private readonly LinkedInRestApi $linkedIn,
        private readonly GraphApi $meta,
    ) {}

    /** @return array{id: string, name: string}|null */
    public function find(string $platform, string $countryCode, string $countryName, ?string $adAccountId = null): ?array
    {
        return match ($platform) {
            'google' => $this->google($countryCode, $adAccountId),
            'linkedin' => $this->linkedIn($countryName, $adAccountId),
            'meta' => $this->meta($countryCode, $countryName, $adAccountId),
            default => throw new RuntimeException('Country lookup is not available for '.$platform.'.'),
        };
    }

    /** @return array{id: string, name: string}|null */
    private function google(string $countryCode, ?string $adAccountId): ?array
    {
        $connection = GoogleAdsConnection::shared()
            ?? throw new RuntimeException(GoogleAdsConnection::missingReason());

        return $this->google->countryGeoTarget($connection, $countryCode, $adAccountId);
    }

    /** @return array{id: string, name: string}|null */
    private function linkedIn(string $countryName, ?string $adAccountId): ?array
    {
        $matches = array_values(array_filter(
            $this->linkedIn->countryCandidates($countryName, $adAccountId),
            static fn (array $candidate): bool => str_starts_with((string) ($candidate['urn'] ?? ''), 'urn:li:geo:')
                && strcasecmp((string) ($candidate['name'] ?? ''), $countryName) === 0,
        ));

        if (count($matches) !== 1) {
            return null;
        }

        return ['id' => (string) $matches[0]['urn'], 'name' => (string) $matches[0]['name']];
    }

    /** @return array{id: string, name: string}|null */
    private function meta(string $countryCode, string $countryName, ?string $adAccountId): ?array
    {
        foreach ($this->meta->countryCandidates($countryName, $adAccountId) as $candidate) {
            if (strcasecmp((string) ($candidate['key'] ?? ''), $countryCode) === 0
                && ($candidate['type'] ?? null) === 'country') {
                return ['id' => $countryCode, 'name' => (string) ($candidate['name'] ?? $countryCode)];
            }
        }

        return null;
    }
}
