<?php
/**
 * ===========================================
 * FLOWBOT DCI - GOOGLE SEARCH ADAPTER
 * ===========================================
 * Google Custom Search API adapter
 *
 * Requirements:
 * - API Key from Google Cloud Console
 * - Custom Search Engine ID (cx)
 *
 * Pricing:
 * - Free: 100 queries/day
 * - Paid: $5 per 1000 queries
 *
 * Setup:
 * 1. Go to Google Cloud Console
 * 2. Enable Custom Search API
 * 3. Create API credentials
 * 4. Create Custom Search Engine at cse.google.com
 * 5. Get the Search Engine ID (cx)
 */

declare(strict_types=1);

namespace FlowbotDCI\Services\SearchEngine;

class GoogleAdapter implements SearchEngineInterface
{
    const NAME = 'Google';
    const API_URL = 'https://www.googleapis.com/customsearch/v1';

    private ?string $apiKey;
    private ?string $cx;
    private ?string $lastError = null;
    private int $timeout = 10;

    public function __construct(array $config = [])
    {
        $this->apiKey = $config['api_key'] ?? null;
        $this->cx = $config['cx'] ?? null;
        $this->timeout = $config['timeout'] ?? 10;
    }

    public function getName(): string
    {
        return self::NAME;
    }

    public function isAvailable(): bool
    {
        return !empty($this->apiKey) && !empty($this->cx);
    }

    public function search(string $query, int $maxResults = 10, int $offset = 0): array
    {
        $this->lastError = null;

        if (!$this->isAvailable()) {
            $this->lastError = 'Google API key or CX not configured';
            return [];
        }

        $results = [];

        try {
            // Google API returns max 10 results per request
            $numResults = min($maxResults, 10);
            $start = $offset + 1; // Google uses 1-based indexing

            $params = [
                'key' => $this->apiKey,
                'cx' => $this->cx,
                'q' => $query,
                'num' => $numResults,
                'start' => $start,
            ];

            $url = self::API_URL . '?' . http_build_query($params);

            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_HTTPHEADER => [
                    'Accept: application/json',
                ],
            ]);

            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($httpCode !== 200) {
                $this->lastError = "HTTP {$httpCode}: " . ($error ?: 'Request failed');

                // Try to parse error from response
                $data = json_decode($response, true);
                if (isset($data['error']['message'])) {
                    $this->lastError = $data['error']['message'];
                }

                return [];
            }

            $data = json_decode($response, true);

            if (isset($data['items']) && is_array($data['items'])) {
                foreach ($data['items'] as $item) {
                    $results[] = [
                        'url' => $item['link'] ?? '',
                        'title' => $item['title'] ?? '',
                        'snippet' => $item['snippet'] ?? '',
                        'source' => self::NAME,
                        'displayLink' => $item['displayLink'] ?? '',
                    ];
                }
            }

            // If more results needed and available, fetch next page
            if (count($results) < $maxResults && isset($data['queries']['nextPage'])) {
                $nextStart = $data['queries']['nextPage'][0]['startIndex'] ?? null;
                if ($nextStart && count($results) < $maxResults) {
                    $remaining = $maxResults - count($results);
                    $nextResults = $this->search($query, $remaining, $nextStart - 1);
                    $results = array_merge($results, $nextResults);
                }
            }

        } catch (\Exception $e) {
            $this->lastError = $e->getMessage();
        }

        return array_slice($results, 0, $maxResults);
    }

    public function getLastError(): ?string
    {
        return $this->lastError;
    }

    /**
     * Get remaining quota (requires additional API call)
     */
    public function getRemainingQuota(): ?int
    {
        // Note: Google doesn't provide a direct way to check quota
        // You'd need to track this yourself or use Cloud Monitoring API
        return null;
    }
}
