<?php

namespace App\Services\Integrations\Discovery;

use App\Models\PlatformConnection;
use App\Services\Credentials\CredentialVault;
use App\Services\Integrations\GoogleOAuthService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Throwable;

class AccountDiscoveryService
{
    public function __construct(
        private readonly CredentialVault $vault,
        private readonly GoogleOAuthService $googleOAuth,
    ) {}

    public function discover(PlatformConnection $connection, int $limit = 50): AccountDiscoveryResult
    {
        $limit = max(1, min($limit, 200));

        return match ($connection->platform) {
            'google_ads' => $this->discoverGoogleAds($connection, $limit),
            'meta_ads' => $this->discoverMetaAds($connection, $limit),
            'search_console' => $this->discoverSearchConsole($connection, $limit),
            'ga4' => $this->discoverGa4($connection, $limit),
            default => AccountDiscoveryResult::failed('Bu platform için hesap keşfi desteklenmiyor: '.$connection->platform),
        };
    }

    private function discoverGoogleAds(PlatformConnection $connection, int $limit): AccountDiscoveryResult
    {
        try {
            $payload = $this->vault->payload($connection->secureCredential);
            $developerToken = $payload['developer_token'] ?? config('services.google_ads.developer_token', env('GOOGLE_ADS_DEVELOPER_TOKEN'));
            $loginCustomerId = $payload['login_customer_id'] ?? null;
            $version = config('services.google_ads.version', env('GOOGLE_ADS_API_VERSION', 'v23'));

            if (blank($developerToken)) {
                return AccountDiscoveryResult::failed('Google Ads developer token eksik. Token kasasına veya .env içine GOOGLE_ADS_DEVELOPER_TOKEN eklenmeli.');
            }

            $accessToken = $this->googleOAuth->accessTokenFromRefreshToken($connection);
            $headers = [
                'Authorization' => 'Bearer '.$accessToken,
                'developer-token' => $developerToken,
            ];

            if (filled($loginCustomerId)) {
                $headers['login-customer-id'] = preg_replace('/\D+/', '', (string) $loginCustomerId);
            }

            $endpoint = "https://googleads.googleapis.com/{$version}/customers:listAccessibleCustomers";
            $response = Http::withHeaders($headers)->timeout(60)->get($endpoint);

            if (! $response->successful()) {
                return AccountDiscoveryResult::failed('Google Ads erişilebilir hesap listesi alınamadı: '.Str::limit($response->body(), 700), $response->json() ?: [], $response->status());
            }

            $resourceNames = array_slice($response->json('resourceNames') ?? [], 0, $limit);
            $accounts = [];

            foreach ($resourceNames as $resourceName) {
                $customerId = preg_replace('/\D+/', '', (string) Str::after($resourceName, 'customers/'));
                if (blank($customerId)) {
                    continue;
                }

                $details = $this->googleCustomerDetails($headers, $version, $customerId);
                $accounts[] = [
                    'platform' => 'google_ads',
                    'account_id' => $customerId,
                    'account_name' => $details['descriptive_name'] ?? 'Google Ads '.$customerId,
                    'currency_code' => $details['currency_code'] ?? null,
                    'timezone' => $details['time_zone'] ?? null,
                    'status' => 'active',
                    'resource_name' => 'customers/'.$customerId,
                    'meta' => [
                        'customer_resource_name' => 'customers/'.$customerId,
                        'source' => 'listAccessibleCustomers',
                    ],
                ];
            }

            return AccountDiscoveryResult::success('Google Ads hesap keşfi tamamlandı. Bulunan hesap: '.count($accounts), $accounts, [
                'total_accessible_customers' => count($response->json('resourceNames') ?? []),
                'listed_customers' => count($accounts),
            ], $response->status());
        } catch (Throwable $e) {
            return AccountDiscoveryResult::failed('Google Ads hesap keşfi başarısız: '.$e->getMessage());
        }
    }

    /**
     * @param array<string, string> $headers
     * @return array<string, mixed>
     */
    private function googleCustomerDetails(array $headers, string $version, string $customerId): array
    {
        $endpoint = "https://googleads.googleapis.com/{$version}/customers/{$customerId}/googleAds:searchStream";
        $query = 'SELECT customer.id, customer.descriptive_name, customer.currency_code, customer.time_zone FROM customer LIMIT 1';
        $response = Http::withHeaders($headers)->timeout(45)->post($endpoint, ['query' => $query]);

        if (! $response->successful()) {
            return [];
        }

        $json = $response->json();
        $row = $json[0]['results'][0]['customer'] ?? [];

        return [
            'id' => $row['id'] ?? $customerId,
            'descriptive_name' => $row['descriptiveName'] ?? $row['descriptive_name'] ?? null,
            'currency_code' => $row['currencyCode'] ?? $row['currency_code'] ?? null,
            'time_zone' => $row['timeZone'] ?? $row['time_zone'] ?? null,
        ];
    }

    private function discoverMetaAds(PlatformConnection $connection, int $limit): AccountDiscoveryResult
    {
        try {
            $payload = $this->vault->payload($connection->secureCredential);
            $token = $payload['access_token'] ?? null;
            $businessId = $payload['business_id'] ?? null;
            $version = config('services.meta.graph_version', env('META_GRAPH_VERSION', 'v23.0'));

            if (blank($token)) {
                return AccountDiscoveryResult::failed('Meta access token eksik. Token kasasına access_token eklenmeli.');
            }

            $accounts = [];
            $responses = [];

            $meEndpoint = "https://graph.facebook.com/{$version}/me/adaccounts";
            $meResponse = Http::timeout(60)->get($meEndpoint, [
                'fields' => 'id,account_id,name,currency,timezone_name,account_status,business{name,id}',
                'limit' => $limit,
                'access_token' => $token,
            ]);
            $responses[] = ['scope' => 'me/adaccounts', 'status' => $meResponse->status()];

            if ($meResponse->successful()) {
                $accounts = array_merge($accounts, $this->mapMetaAccounts($meResponse->json('data') ?? []));
            }

            if (filled($businessId)) {
                foreach (['owned_ad_accounts', 'client_ad_accounts'] as $edge) {
                    if (count($accounts) >= $limit) {
                        break;
                    }

                    $endpoint = "https://graph.facebook.com/{$version}/{$businessId}/{$edge}";
                    $response = Http::timeout(60)->get($endpoint, [
                        'fields' => 'id,account_id,name,currency,timezone_name,account_status,business{name,id}',
                        'limit' => $limit,
                        'access_token' => $token,
                    ]);
                    $responses[] = ['scope' => $edge, 'status' => $response->status()];

                    if ($response->successful()) {
                        $accounts = array_merge($accounts, $this->mapMetaAccounts($response->json('data') ?? [], $edge));
                    }
                }
            }

            $accounts = collect($accounts)
                ->unique('account_id')
                ->take($limit)
                ->values()
                ->all();

            if (empty($accounts) && ! $meResponse->successful()) {
                return AccountDiscoveryResult::failed('Meta reklam hesabı listesi alınamadı: '.Str::limit($meResponse->body(), 700), $meResponse->json() ?: [], $meResponse->status());
            }

            return AccountDiscoveryResult::success('Meta reklam hesabı keşfi tamamlandı. Bulunan hesap: '.count($accounts), $accounts, [
                'responses' => $responses,
            ], $meResponse->status());
        } catch (Throwable $e) {
            return AccountDiscoveryResult::failed('Meta hesap keşfi başarısız: '.$e->getMessage());
        }
    }

    /**
     * @param array<int, array<string, mixed>> $rows
     * @return array<int, array<string, mixed>>
     */
    private function mapMetaAccounts(array $rows, string $source = 'me/adaccounts'): array
    {
        return collect($rows)->map(function (array $row) use ($source) {
            $id = $row['id'] ?? null;
            $accountId = $id ?: (filled($row['account_id'] ?? null) ? 'act_'.$row['account_id'] : null);

            return [
                'platform' => 'meta_ads',
                'account_id' => $accountId,
                'account_name' => $row['name'] ?? $accountId,
                'currency_code' => $row['currency'] ?? null,
                'timezone' => $row['timezone_name'] ?? null,
                'status' => ($row['account_status'] ?? null) == 1 ? 'active' : 'paused',
                'resource_name' => $accountId,
                'meta' => [
                    'account_id_numeric' => $row['account_id'] ?? null,
                    'account_status' => $row['account_status'] ?? null,
                    'business' => $row['business'] ?? null,
                    'source' => $source,
                ],
            ];
        })->filter(fn (array $row) => filled($row['account_id']))->values()->all();
    }

    private function discoverSearchConsole(PlatformConnection $connection, int $limit): AccountDiscoveryResult
    {
        try {
            $accessToken = $this->googleOAuth->accessTokenFromRefreshToken($connection);
            $endpoint = 'https://www.googleapis.com/webmasters/v3/sites';
            $response = Http::withToken($accessToken)->timeout(60)->get($endpoint);

            if (! $response->successful()) {
                return AccountDiscoveryResult::failed('Search Console mülkleri alınamadı: '.Str::limit($response->body(), 700), $response->json() ?: [], $response->status());
            }

            $accounts = collect($response->json('siteEntry') ?? [])
                ->take($limit)
                ->map(fn (array $row) => [
                    'platform' => 'search_console',
                    'account_id' => $row['siteUrl'] ?? null,
                    'account_name' => $row['siteUrl'] ?? null,
                    'currency_code' => null,
                    'timezone' => null,
                    'status' => 'active',
                    'resource_name' => $row['siteUrl'] ?? null,
                    'meta' => [
                        'permission_level' => $row['permissionLevel'] ?? null,
                        'source' => 'webmasters.sites.list',
                    ],
                ])
                ->filter(fn (array $row) => filled($row['account_id']))
                ->values()
                ->all();

            return AccountDiscoveryResult::success('Search Console mülk keşfi tamamlandı. Bulunan mülk: '.count($accounts), $accounts, [
                'total_sites' => count($response->json('siteEntry') ?? []),
            ], $response->status());
        } catch (Throwable $e) {
            return AccountDiscoveryResult::failed('Search Console keşfi başarısız: '.$e->getMessage());
        }
    }

    private function discoverGa4(PlatformConnection $connection, int $limit): AccountDiscoveryResult
    {
        try {
            $accessToken = $this->googleOAuth->accessTokenFromRefreshToken($connection);
            $endpoint = 'https://analyticsadmin.googleapis.com/v1beta/accountSummaries';
            $response = Http::withToken($accessToken)->timeout(60)->get($endpoint, ['pageSize' => $limit]);

            if (! $response->successful()) {
                return AccountDiscoveryResult::failed('GA4 property listesi alınamadı: '.Str::limit($response->body(), 700), $response->json() ?: [], $response->status());
            }

            $accounts = [];
            foreach ($response->json('accountSummaries') ?? [] as $summary) {
                foreach ($summary['propertySummaries'] ?? [] as $property) {
                    if (count($accounts) >= $limit) {
                        break 2;
                    }

                    $propertyResourceName = $property['property'] ?? null;
                    $propertyId = filled($propertyResourceName) ? Str::after($propertyResourceName, 'properties/') : null;
                    $accounts[] = [
                        'platform' => 'ga4',
                        'account_id' => $propertyId,
                        'account_name' => $property['displayName'] ?? ('GA4 Property '.$propertyId),
                        'currency_code' => null,
                        'timezone' => null,
                        'status' => 'active',
                        'resource_name' => $propertyResourceName,
                        'meta' => [
                            'account' => $summary['account'] ?? null,
                            'account_display_name' => $summary['displayName'] ?? null,
                            'property_resource_name' => $propertyResourceName,
                            'property_type' => $property['propertyType'] ?? null,
                            'source' => 'analyticsadmin.accountSummaries.list',
                        ],
                    ];
                }
            }

            return AccountDiscoveryResult::success('GA4 property keşfi tamamlandı. Bulunan property: '.count($accounts), $accounts, [
                'total_account_summaries' => count($response->json('accountSummaries') ?? []),
            ], $response->status());
        } catch (Throwable $e) {
            return AccountDiscoveryResult::failed('GA4 keşfi başarısız: '.$e->getMessage());
        }
    }
}
