<?php

namespace App\Services;

use App\Models\ProviderCredential;
use App\Models\AuditLog;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Exception;

class ProviderCredentialService
{
    /**
     * Test provider connection with read-only API call.
     */
    public function testConnection(ProviderCredential $credential): array
    {
        try {
            $result = match($credential->provider) {
                'youtube' => $this->testYouTube($credential),
                'instagram' => $this->testInstagram($credential),
                'tiktok' => $this->testTikTok($credential),
                'linkedin' => $this->testLinkedIn($credential),
                'twitter' => $this->testTwitter($credential),
                'facebook_ads' => $this->testFacebookAds($credential),
                'google_ads' => $this->testGoogleAds($credential),
                'custom' => $this->testCustomProvider($credential),
                default => throw new Exception("Unsupported provider: {$credential->provider}"),
            };

            // Update credential status
            $credential->update([
                'status' => 'connected',
                'last_tested_at' => now(),
                'last_error' => null,
            ]);

            // Log successful test
            $this->logAudit($credential, 'test_connection_success');

            return [
                'success' => true,
                'message' => 'Connection successful',
                'data' => $result,
            ];

        } catch (Exception $e) {
            // Update credential with error
            $credential->update([
                'status' => 'failed',
                'last_tested_at' => now(),
                'last_error' => $e->getMessage(),
            ]);

            // Log failed test
            $this->logAudit($credential, 'test_connection_failed', [
                'error' => $e->getMessage(),
            ]);

            Log::error("Provider connection test failed", [
                'provider' => $credential->provider,
                'credential_id' => $credential->id,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'message' => $this->getUserFriendlyError($e->getMessage()),
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * Test YouTube connection.
     */
    protected function testYouTube(ProviderCredential $credential): array
    {
        $response = Http::withToken($credential->access_token)
            ->get('https://www.googleapis.com/youtube/v3/channels', [
                'part' => 'snippet',
                'mine' => 'true',
            ]);

        if (!$response->successful()) {
            throw new Exception("YouTube API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'channel_name' => $data['items'][0]['snippet']['title'] ?? 'Unknown',
            'channel_id' => $data['items'][0]['id'] ?? null,
        ];
    }

    /**
     * Test Instagram connection.
     */
    protected function testInstagram(ProviderCredential $credential): array
    {
        $response = Http::get('https://graph.instagram.com/me', [
            'fields' => 'id,username',
            'access_token' => $credential->access_token,
        ]);

        if (!$response->successful()) {
            throw new Exception("Instagram API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'username' => $data['username'] ?? 'Unknown',
            'user_id' => $data['id'] ?? null,
        ];
    }

    /**
     * Test TikTok connection.
     */
    protected function testTikTok(ProviderCredential $credential): array
    {
        $response = Http::withToken($credential->access_token)
            ->get('https://open-api.tiktok.com/user/info/');

        if (!$response->successful()) {
            throw new Exception("TikTok API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'username' => $data['data']['user']['display_name'] ?? 'Unknown',
            'user_id' => $data['data']['user']['open_id'] ?? null,
        ];
    }

    /**
     * Test LinkedIn connection.
     */
    protected function testLinkedIn(ProviderCredential $credential): array
    {
        $response = Http::withToken($credential->access_token)
            ->get('https://api.linkedin.com/v2/me');

        if (!$response->successful()) {
            throw new Exception("LinkedIn API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'name' => ($data['localizedFirstName'] ?? '') . ' ' . ($data['localizedLastName'] ?? ''),
            'user_id' => $data['id'] ?? null,
        ];
    }

    /**
     * Test Twitter/X connection.
     */
    protected function testTwitter(ProviderCredential $credential): array
    {
        $response = Http::withToken($credential->access_token)
            ->get('https://api.twitter.com/2/users/me');

        if (!$response->successful()) {
            throw new Exception("Twitter API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'username' => $data['data']['username'] ?? 'Unknown',
            'user_id' => $data['data']['id'] ?? null,
        ];
    }

    /**
     * Test Facebook Ads connection.
     */
    protected function testFacebookAds(ProviderCredential $credential): array
    {
        $adAccountId = $credential->ad_account_id;
        
        $response = Http::get("https://graph.facebook.com/v18.0/{$adAccountId}", [
            'fields' => 'name,account_status',
            'access_token' => $credential->access_token,
        ]);

        if (!$response->successful()) {
            throw new Exception("Facebook Ads API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'account_name' => $data['name'] ?? 'Unknown',
            'account_status' => $data['account_status'] ?? null,
            'account_id' => $adAccountId,
        ];
    }

    /**
     * Test Google Ads connection.
     */
    protected function testGoogleAds(ProviderCredential $credential): array
    {
        $response = Http::withToken($credential->access_token)
            ->get('https://googleads.googleapis.com/v14/customers:listAccessibleCustomers');

        if (!$response->successful()) {
            throw new Exception("Google Ads API error: " . $response->body());
        }

        $data = $response->json();
        
        return [
            'accessible_customers' => count($data['resourceNames'] ?? []),
            'customer_ids' => $data['resourceNames'] ?? [],
        ];
    }

    /**
     * Test custom provider connection.
     */
    protected function testCustomProvider(ProviderCredential $credential): array
    {
        // For custom providers, we'll just verify the token exists
        if (empty($credential->access_token)) {
            throw new Exception("Access token is required for custom provider");
        }

        return [
            'message' => 'Custom provider credentials stored successfully',
            'note' => 'Please test the connection manually with your API',
        ];
    }

    /**
     * Refresh OAuth token.
     */
    public function refreshToken(ProviderCredential $credential): bool
    {
        if (empty($credential->refresh_token)) {
            return false;
        }

        try {
            $result = match($credential->provider) {
                'youtube', 'google_ads' => $this->refreshGoogleToken($credential),
                'instagram', 'facebook_ads' => $this->refreshFacebookToken($credential),
                'linkedin' => $this->refreshLinkedInToken($credential),
                'twitter' => $this->refreshTwitterToken($credential),
                default => false,
            };

            if ($result) {
                $this->logAudit($credential, 'token_refreshed');
            }

            return $result;

        } catch (Exception $e) {
            Log::error("Token refresh failed", [
                'provider' => $credential->provider,
                'credential_id' => $credential->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Refresh Google OAuth token.
     */
    protected function refreshGoogleToken(ProviderCredential $credential): bool
    {
        $response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
            'client_id' => $credential->client_id,
            'client_secret' => $credential->client_secret,
            'refresh_token' => $credential->refresh_token,
            'grant_type' => 'refresh_token',
        ]);

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

        $data = $response->json();
        
        $credential->update([
            'access_token' => $data['access_token'],
            'token_expires_at' => now()->addSeconds($data['expires_in'] ?? 3600),
            'expiry_alert_sent' => false,
        ]);

        return true;
    }

    /**
     * Refresh Facebook OAuth token.
     */
    protected function refreshFacebookToken(ProviderCredential $credential): bool
    {
        $response = Http::get('https://graph.facebook.com/v18.0/oauth/access_token', [
            'grant_type' => 'fb_exchange_token',
            'client_id' => $credential->client_id,
            'client_secret' => $credential->client_secret,
            'fb_exchange_token' => $credential->access_token,
        ]);

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

        $data = $response->json();
        
        $credential->update([
            'access_token' => $data['access_token'],
            'token_expires_at' => now()->addSeconds($data['expires_in'] ?? 5184000), // 60 days default
            'expiry_alert_sent' => false,
        ]);

        return true;
    }

    /**
     * Refresh LinkedIn OAuth token.
     */
    protected function refreshLinkedInToken(ProviderCredential $credential): bool
    {
        $response = Http::asForm()->post('https://www.linkedin.com/oauth/v2/accessToken', [
            'grant_type' => 'refresh_token',
            'refresh_token' => $credential->refresh_token,
            'client_id' => $credential->client_id,
            'client_secret' => $credential->client_secret,
        ]);

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

        $data = $response->json();
        
        $credential->update([
            'access_token' => $data['access_token'],
            'refresh_token' => $data['refresh_token'] ?? $credential->refresh_token,
            'token_expires_at' => now()->addSeconds($data['expires_in'] ?? 5184000),
            'expiry_alert_sent' => false,
        ]);

        return true;
    }

    /**
     * Refresh Twitter OAuth token.
     */
    protected function refreshTwitterToken(ProviderCredential $credential): bool
    {
        $response = Http::asForm()
            ->withBasicAuth($credential->client_id, $credential->client_secret)
            ->post('https://api.twitter.com/2/oauth2/token', [
                'grant_type' => 'refresh_token',
                'refresh_token' => $credential->refresh_token,
            ]);

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

        $data = $response->json();
        
        $credential->update([
            'access_token' => $data['access_token'],
            'refresh_token' => $data['refresh_token'] ?? $credential->refresh_token,
            'token_expires_at' => now()->addSeconds($data['expires_in'] ?? 7200),
            'expiry_alert_sent' => false,
        ]);

        return true;
    }

    /**
     * Log audit trail.
     */
    protected function logAudit(ProviderCredential $credential, string $action, array $meta = []): void
    {
        AuditLog::create([
            'actor_id' => auth()->id(),
            'action' => $action,
            'target_type' => ProviderCredential::class,
            'target_id' => $credential->id,
            'meta' => array_merge([
                'provider' => $credential->provider,
                'label' => $credential->label,
                'brand_id' => $credential->brand_id,
            ], $meta),
        ]);
    }

    /**
     * Get user-friendly error message.
     */
    protected function getUserFriendlyError(string $error): string
    {
        if (str_contains($error, 'invalid_grant')) {
            return 'Your access token has expired or been revoked. Please reconnect your account.';
        }

        if (str_contains($error, 'invalid_client')) {
            return 'Invalid client credentials. Please check your Client ID and Client Secret.';
        }

        if (str_contains($error, 'insufficient_scope')) {
            return 'Insufficient permissions. Please reconnect with the required scopes.';
        }

        if (str_contains($error, 'rate_limit')) {
            return 'Rate limit exceeded. Please try again later.';
        }

        if (str_contains($error, 'unauthorized')) {
            return 'Authentication failed. Please check your credentials and try again.';
        }

        return 'Connection test failed. Please verify your credentials and try again.';
    }
}