<?php

declare(strict_types=1);

namespace App\Services;

use App\Core\Config;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class DataForSeoService
{
    private Client $http;

    public function __construct()
    {
        $timeout = (float) Config::getDbSetting(
            'dataforseo_timeout_seconds',
            Config::get('DATAFORSEO_TIMEOUT_SECONDS', '30')
        );

        $this->http = new Client([
            'timeout' => max(5, $timeout),
            'verify' => false,
        ]);
    }

    public function fetchIndexedPagesCount(string $domain): array
    {
        $baseUrl = rtrim((string) Config::getDbSetting(
            'dataforseo_api_base',
            Config::get('DATAFORSEO_API_BASE', 'https://api.dataforseo.com')
        ), '/');
        $login = trim((string) Config::getDbSetting('dataforseo_login', Config::get('DATAFORSEO_LOGIN', '')));
        $password = trim((string) Config::getDbSetting('dataforseo_password', Config::get('DATAFORSEO_PASSWORD', '')));
        $locationCode = (int) Config::getDbSetting('dataforseo_location_code', Config::get('DATAFORSEO_LOCATION_CODE', '2616'));
        $languageCode = strtolower(trim((string) Config::getDbSetting(
            'dataforseo_language_code',
            Config::get('DATAFORSEO_LANGUAGE_CODE', 'pl')
        )));

        if ($login === '' || $password === '') {
            throw new \RuntimeException('Brak danych logowania DataForSEO (login/haslo).');
        }

        if ($locationCode <= 0) {
            $locationCode = 2616;
        }

        if ($languageCode === '') {
            $languageCode = 'pl';
        }

        $payload = [[
            'keyword' => 'site:' . $domain,
            'location_code' => $locationCode,
            'language_code' => $languageCode,
            'device' => 'desktop',
            'os' => 'windows',
            'depth' => 10,
        ]];

        try {
            $response = $this->http->post($baseUrl . '/v3/serp/google/organic/live/regular', [
                'headers' => [
                    'Accept' => 'application/json',
                    'Content-Type' => 'application/json',
                    'User-Agent' => 'BackPRO/1.0',
                ],
                'auth' => [$login, $password],
                'json' => $payload,
            ]);
        } catch (GuzzleException $e) {
            throw new \RuntimeException('Blad pobierania statystyk DataForSEO: ' . $e->getMessage(), 0, $e);
        }

        $raw = (string) $response->getBody();
        $decoded = json_decode($raw, true);
        if (!is_array($decoded)) {
            throw new \RuntimeException('DataForSEO zwrocil niepoprawny JSON.');
        }

        return [
            'indexed_pages' => $this->extractIndexedPages($decoded),
            'payload' => $raw,
        ];
    }

    private function extractIndexedPages(array $payload): int
    {
        $tasks = $payload['tasks'] ?? null;
        if (!is_array($tasks) || empty($tasks) || !is_array($tasks[0] ?? null)) {
            return 0;
        }

        $task = $tasks[0];
        $result = null;
        if (is_array($task['result'] ?? null) && !empty($task['result'][0]) && is_array($task['result'][0])) {
            $result = $task['result'][0];
        }

        if (!is_array($result)) {
            return 0;
        }

        // Prefer dedicated total counters from SERP response.
        if (isset($result['se_results_count'])) {
            return max(0, (int) $result['se_results_count']);
        }

        if (isset($result['items_count'])) {
            return max(0, (int) $result['items_count']);
        }

        return 0;
    }
}

