<?php
namespace Crawl\Services;

/**
 * Fetches Core Web Vitals + performance metrics via Google PageSpeed Insights API.
 * Requires PAGESPEED_API_KEY in .env
 */
class PageSpeedService
{
    private string $apiKey;
    private int    $timeout = 20;

    public function __construct()
    {
        $this->apiKey = $_ENV['PAGESPEED_API_KEY'] ?? '';
    }

    public function isConfigured(): bool
    {
        return $this->apiKey !== '';
    }

    /**
     * Run PSI for a URL. Strategy: 'mobile' or 'desktop'.
     */
    public function analyse(string $url, string $strategy = 'mobile'): array
    {
        if (!$this->isConfigured()) {
            return ['error' => 'PAGESPEED_API_KEY not configured in .env'];
        }

        $endpoint = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed?' . http_build_query([
            'url'      => $url,
            'strategy' => $strategy,
            'key'      => $this->apiKey,
            'category' => ['performance', 'seo', 'accessibility', 'best-practices'],
        ], '', '&', PHP_QUERY_RFC3986);

        $ch = curl_init($endpoint);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => $this->timeout,
            CURLOPT_USERAGENT      => 'Savit AuditEngine/1.0',
        ]);
        $body = (string)curl_exec($ch);
        $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $err  = curl_error($ch);
        curl_close($ch);

        if ($err !== '' || $code !== 200) {
            return ['error' => "PSI request failed (HTTP {$code}): {$err}"];
        }

        $data = json_decode($body, true);
        if (!$data) return ['error' => 'Invalid JSON from PSI API'];

        return $this->extract($data, $strategy);
    }

    /**
     * Run both mobile and desktop for a domain's homepage.
     */
    public function analyseUrl(string $url): array
    {
        return [
            'mobile'  => $this->analyse($url, 'mobile'),
            'desktop' => $this->analyse($url, 'desktop'),
        ];
    }

    private function extract(array $data, string $strategy): array
    {
        $cats     = $data['lighthouseResult']['categories'] ?? [];
        $audits   = $data['lighthouseResult']['audits']     ?? [];
        $metrics  = $audits['metrics']['details']['items'][0] ?? [];

        $score = fn(string $key): int => (int)round(($cats[$key]['score'] ?? 0) * 100);

        $ms = fn(string $key): ?int => isset($metrics[$key]) ? (int)$metrics[$key] : null;

        // Core Web Vitals from field data (crux)
        $crux = $data['loadingExperience']['metrics'] ?? [];
        $cruxVal = fn(string $key): ?string => $crux[$key]['percentile'] ?? null;

        return [
            'strategy'             => $strategy,
            'url'                  => $data['id'] ?? '',
            'scores'               => [
                'performance'   => $score('performance'),
                'seo'           => $score('seo'),
                'accessibility' => $score('accessibility'),
                'best_practices'=> $score('best-practices'),
            ],
            'lab_metrics'          => [
                'fcp_ms'   => $ms('firstContentfulPaint'),
                'lcp_ms'   => $ms('largestContentfulPaint'),
                'tbt_ms'   => $ms('totalBlockingTime'),
                'cls'      => $audits['cumulative-layout-shift']['displayValue'] ?? null,
                'si_ms'    => $ms('speedIndex'),
                'tti_ms'   => $ms('interactive'),
            ],
            'field_data'           => [
                'fcp_ms' => $cruxVal('FIRST_CONTENTFUL_PAINT_MS'),
                'lcp_ms' => $cruxVal('LARGEST_CONTENTFUL_PAINT_MS'),
                'fid_ms' => $cruxVal('FIRST_INPUT_DELAY_MS'),
                'cls'    => $cruxVal('CUMULATIVE_LAYOUT_SHIFT_SCORE'),
            ],
            'opportunities'        => $this->extractOpportunities($audits),
        ];
    }

    private function extractOpportunities(array $audits): array
    {
        $keys = [
            'render-blocking-resources', 'uses-optimized-images', 'uses-webp-images',
            'uses-text-compression', 'unused-css-rules', 'unused-javascript',
            'uses-long-cache-ttl', 'efficient-animated-content',
        ];
        $out = [];
        foreach ($keys as $key) {
            $a = $audits[$key] ?? null;
            if (!$a || ($a['score'] ?? 1) >= 1) continue;
            $out[] = [
                'id'          => $key,
                'title'       => $a['title']        ?? $key,
                'description' => $a['description']  ?? '',
                'savings_ms'  => (int)($a['details']['overallSavingsMs'] ?? 0),
            ];
        }
        usort($out, fn($a, $b) => $b['savings_ms'] - $a['savings_ms']);
        return $out;
    }
}
