<?php
/**
 * ===========================================
 * FLOWBOT DCI - BRAVE SEARCH ADAPTER
 * ===========================================
 * Uses Brave Search API - FREE TIER: 2000 queries/month
 *
 * Get API key at: https://brave.com/search/api/
 * - Create account
 * - Subscribe to "Free" plan (2000 queries/month)
 * - Copy API key to .env as SEARCH_BRAVE_API_KEY
 */

declare(strict_types=1);

namespace FlowbotDCI\Services\SearchEngine;

class BraveAdapter implements SearchEngineInterface
{
    const NAME = 'Brave';
    const API_URL = 'https://api.search.brave.com/res/v1/web/search';

    private ?string $apiKey = null;
    private ?string $lastError = null;
    private int $timeout = 15;

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

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

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

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

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

        $results = [];

        try {
            $url = self::API_URL . '?' . http_build_query([
                'q' => $query,
                'count' => min($maxResults, 20), // Brave max is 20
                'offset' => $offset,
                'safesearch' => 'moderate',
            ]);

            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_HTTPHEADER => [
                    'Accept: application/json',
                    'Accept-Encoding: gzip',
                    'X-Subscription-Token: ' . $this->apiKey,
                ],
                CURLOPT_ENCODING => 'gzip',
                CURLOPT_SSL_VERIFYPEER => true,
                CURLOPT_SSL_VERIFYHOST => 2,
            ]);

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

            if ($httpCode !== 200) {
                $this->lastError = "Brave API returned HTTP {$httpCode}";
                if ($httpCode === 401) {
                    $this->lastError = "Invalid Brave API key";
                } elseif ($httpCode === 429) {
                    $this->lastError = "Brave API rate limit exceeded (2000/month free)";
                }
                return [];
            }

            if (empty($response)) {
                $this->lastError = "Empty response from Brave API: {$error}";
                return [];
            }

            $data = json_decode($response, true);
            if (!is_array($data)) {
                $this->lastError = "Invalid JSON response from Brave API";
                return [];
            }

            // Parse web results
            $webResults = $data['web']['results'] ?? [];

            foreach ($webResults as $item) {
                $url = $item['url'] ?? '';
                $title = $item['title'] ?? '';

                if (empty($url) || empty($title)) {
                    continue;
                }

                if (!filter_var($url, FILTER_VALIDATE_URL)) {
                    continue;
                }

                $results[] = [
                    'url' => $url,
                    'title' => html_entity_decode($title, ENT_QUOTES, 'UTF-8'),
                    'snippet' => html_entity_decode($item['description'] ?? '', ENT_QUOTES, 'UTF-8'),
                    'source' => self::NAME,
                    'favicon' => $item['meta_url']['favicon'] ?? null,
                ];

                if (count($results) >= $maxResults) {
                    break;
                }
            }

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

        return $results;
    }

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