<?php

namespace App\Services\Keywords;

use App\Models\PlatformConnection;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V25\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V25\GoogleAdsClientBuilder;
use InvalidArgumentException;

class GoogleAdsClientFactory
{
    /**
     * @return list<string>
     */
    public function missingConfigurationKeys(): array
    {
        $missing = [];
        $configuration = $this->configuration();

        foreach ([
            'developer_token' => 'GOOGLE_ADS_DEVELOPER_TOKEN',
            'client_id' => 'GOOGLE_ADS_CLIENT_ID',
            'client_secret' => 'GOOGLE_ADS_CLIENT_SECRET',
            'refresh_token' => 'GOOGLE_ADS_REFRESH_TOKEN',
        ] as $configKey => $envKey) {
            if (! filled($configuration[$configKey])) {
                $missing[] = $envKey;
            }
        }

        return $missing;
    }

    public function make(): GoogleAdsClient
    {
        $configuration = $this->configuration();
        $missing = $this->missingConfigurationKeys();

        if ($missing !== []) {
            throw new InvalidArgumentException(
                'Missing Google Ads configuration: '.implode(', ', $missing),
            );
        }

        $oAuth2Credential = (new OAuth2TokenBuilder)
            ->withClientId((string) $configuration['client_id'])
            ->withClientSecret((string) $configuration['client_secret'])
            ->withRefreshToken((string) $configuration['refresh_token'])
            ->build();

        $builder = (new GoogleAdsClientBuilder)
            ->withDeveloperToken((string) $configuration['developer_token'])
            ->withOAuth2Credential($oAuth2Credential);

        $loginCustomerId = $this->normalizeCustomerId($configuration['login_customer_id']);

        if ($loginCustomerId !== null) {
            $builder->withLoginCustomerId($loginCustomerId);
        }

        return $builder->build();
    }

    public function resolveCustomerId(): ?string
    {
        $configuration = $this->configuration();
        $configuredCustomerId = $this->normalizeCustomerId($configuration['customer_id']);

        if ($configuredCustomerId !== null) {
            return (string) $configuredCustomerId;
        }

        $loginCustomerId = $this->normalizeCustomerId($configuration['login_customer_id']);

        return $loginCustomerId !== null ? (string) $loginCustomerId : null;
    }

    public function normalizeCustomerId(mixed $customerId): ?int
    {
        if (! filled($customerId)) {
            return null;
        }

        $digits = preg_replace('/\D+/', '', (string) $customerId);

        if ($digits === null || $digits === '') {
            return null;
        }

        return (int) $digits;
    }

    /** @return array<string, mixed> */
    private function configuration(): array
    {
        $connection = PlatformConnection::shared('google');

        return [
            'developer_token' => $connection?->platform_secrets['developer_token'] ?? config('google-ads.developer_token'),
            'client_id' => $connection?->platform_data['client_id'] ?? config('google-ads.client_id'),
            'client_secret' => $connection?->platform_secrets['client_secret'] ?? config('google-ads.client_secret'),
            'refresh_token' => $connection?->refresh_token ?? config('google-ads.refresh_token'),
            'login_customer_id' => $connection?->platform_data['manager_customer_id'] ?? config('google-ads.login_customer_id'),
            'customer_id' => $connection?->account_id ?? config('google-ads.customer_id'),
        ];
    }
}
