<?php

namespace App\Services;

use App\Models\KeywordMetricsCache;
use App\Models\ApiUsageLog;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class DataForSEOClient
{
    private string $login;
    private string $password;
    private string $baseUrl = 'https://api.dataforseo.com/v3';
    private int $rateLimitMs;

    public function __construct()
    {
        $this->login = config('services.dataforseo.login');
        $this->password = config('services.dataforseo.password');
        $this->rateLimitMs = config('services.dataforseo.rate_limit_ms', 50);
    }

    /**
     * Get search volume for keywords with caching
     */
    public function getSearchVolume(array $keywords, int $locationCode = 2840, string $languageCode = 'en'): array
    {
        // Check cache for all keywords
        $results = [];
        $uncachedKeywords = [];

        foreach ($keywords as $keyword) {
            $cached = KeywordMetricsCache::getCachedMetrics($keyword, $locationCode);
            if ($cached) {
                $results[$keyword] = $cached;
            } else {
                $uncachedKeywords[] = $keyword;
            }
        }

        // If all keywords are cached, return early
        if (empty($uncachedKeywords)) {
            Log::info('DataForSEO: All keywords cached', ['count' => count($keywords)]);
            return $results;
        }

        // Rate limiting
        usleep($this->rateLimitMs * 1000);

        // Fetch uncached keywords (max 1000 per request)
        $batches = array_chunk($uncachedKeywords, 1000);

        foreach ($batches as $batch) {
            try {
                $response = $this->makeRequest('/keywords_data/google_ads/search_volume/live', [
                    [
                        'location_code' => $locationCode,
                        'language_code' => $languageCode,
                        'keywords' => $batch,
                        'search_partners' => false,
                    ]
                ]);

                if ($response && isset($response['tasks'][0]['result'])) {
                    foreach ($response['tasks'][0]['result'] as $item) {
                        $keyword = $item['keyword'];
                        $metrics = [
                            'search_volume' => $item['search_volume'] ?? 0,
                            'competition' => $item['competition'] ?? 'UNKNOWN',
                            'competition_index' => $item['competition_index'] ?? 0,
                            'cpc' => $item['cpc'] ?? 0,
                        ];

                        // Cache the metrics
                        $cacheDays = config('services.dataforseo.cache_days', 7);
                        KeywordMetricsCache::cacheMetrics($keyword, $metrics, $locationCode, $cacheDays);

                        $results[$keyword] = $metrics;
                    }
                }

                // Log API usage
                $cost = $response['cost'] ?? 0.025;
                ApiUsageLog::logUsage('dataforseo', $cost);

            } catch (\Exception $e) {
                Log::error('DataForSEO search volume failed', [
                    'error' => $e->getMessage(),
                    'keywords_count' => count($batch),
                ]);
            }

            // Rate limiting between batches
            if (count($batches) > 1) {
                sleep(5);
            }
        }

        return $results;
    }

    /**
     * Make API request to DataForSEO
     */
    private function makeRequest(string $endpoint, array $payload): ?array
    {
        $url = $this->baseUrl . $endpoint;

        try {
            $response = Http::withBasicAuth($this->login, $this->password)
                ->withHeaders(['Content-Type' => 'application/json'])
                ->timeout(60)
                ->post($url, $payload);

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

            $data = $response->json();

            if ($data['status_code'] !== 20000) {
                throw new \Exception('DataForSEO error: ' . $data['status_message']);
            }

            return $data;

        } catch (\Exception $e) {
            Log::error('DataForSEO request failed', [
                'endpoint' => $endpoint,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }
}
