<?php

namespace Tests\Unit\Services\AI;

use App\Services\AI\WebsiteBrandSignalExtractor;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Process;
use Tests\TestCase;

class WebsiteBrandSignalExtractorTest extends TestCase
{
    public function test_scan_reads_logo_svg_and_theme_color_from_http_html_when_puppeteer_fails(): void
    {
        $this->fakeFailedPuppeteer();
        Http::preventStrayRequests();
        Http::fake([
            'https://brand.example.com' => Http::response(
                '<html><head><meta name="theme-color" content="#860edf"><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap"><style>body{font-family:"Montserrat",sans-serif;color:#111111}</style></head><body><svg class="logo" viewBox="0 0 10 10"><path d="M0 0h10v10H0z" fill="#860edf"/></svg></body></html>'
            ),
            'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap' => Http::response(
                "@font-face{font-family:'Montserrat';}"
            ),
            'https://brand.example.com/favicon.ico' => Http::response('', 404),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://brand.example.com');

        $this->assertNotNull($signals);
        $this->assertTrue($signals->hasExactLogoSvg());
        $this->assertStringContainsString('<svg', (string) $signals->exactLogoSvg);
        $this->assertStringContainsString('Declared theme-color meta tag: #860edf', $signals->summaryText);
        $this->assertStringContainsString('#111111', $signals->summaryText);
        $this->assertSame('Montserrat', $signals->fontFamily);
        $this->assertSame(
            'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap',
            $signals->fontStylesheetUrl,
        );
        $this->assertStringContainsString('Body font-family from the live page', $signals->summaryText);
        $this->assertStringContainsString('Montserrat', $signals->summaryText);
    }

    public function test_scan_prefers_puppeteer_header_color_and_logo_over_stylesheet_hexes(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result(json_encode([
                'headerColor' => '#7c5cff',
                'colorSource' => 'cta',
                'headerBackground' => '#ffffff',
                'fontFamily' => 'Inter, system-ui, sans-serif',
                'fontStylesheet' => 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
                'logo' => [
                    'kind' => 'img',
                    'src' => 'https://lucos.example.com/assets/img/logo-light.png',
                ],
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://lucos.example.com' => Http::response(
                '<html><head><link rel="stylesheet" href="https://cdn.example.com/bootstrap.css"></head><body><a class="btn-success">Go</a></body></html>'
            ),
            'https://cdn.example.com/bootstrap.css' => Http::response('.btn-success{color:#198754}.btn-primary{color:#0d6efd}'),
            'https://lucos.example.com/assets/img/logo-light.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
            'https://lucos.example.com/favicon.ico' => Http::response('', 404),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://lucos.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('#7c5cff', $signals->headerColor);
        $this->assertSame('#ffffff', $signals->headerBackgroundColor);
        $this->assertSame('https://lucos.example.com/assets/img/logo-light.png', $signals->logoPublicUrl);
        $this->assertSame('Inter', $signals->fontFamily);
        $this->assertSame(
            'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
            $signals->fontStylesheetUrl,
        );
        $this->assertStringContainsString('Header CTA color from the live page (use as accent_color / theme): #7c5cff', $signals->summaryText);
        $this->assertStringContainsString('Stylesheet hex colors were ignored', $signals->summaryText);
        $this->assertStringNotContainsString('#198754', $signals->summaryText);
        $this->assertStringNotContainsString('#0d6efd', $signals->summaryText);

        if ($signals->logoImagePath !== null) {
            @unlink($signals->logoImagePath);
        }
    }

    public function test_scan_falls_back_to_header_background_when_puppeteer_finds_no_cta(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result(json_encode([
                'headerColor' => '#1e1b4b',
                'colorSource' => 'header',
                'logo' => null,
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://nav.example.com' => Http::response('<html></html>'),
            'https://nav.example.com/favicon.ico' => Http::response('', 404),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://nav.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('#1e1b4b', $signals->headerColor);
        $this->assertStringContainsString('Header background color from the live page: #1e1b4b', $signals->summaryText);
    }

    public function test_scan_returns_null_when_puppeteer_and_http_both_fail(): void
    {
        $this->fakeFailedPuppeteer();
        Http::preventStrayRequests();
        Http::fake([
            'https://missing.example.com' => Http::response('Not found', 404),
        ]);

        $this->assertNull((new WebsiteBrandSignalExtractor)->scan('https://missing.example.com'));
    }

    public function test_scan_uses_the_site_favicon_as_the_header_logo_when_no_logo_exists(): void
    {
        $this->fakeFailedPuppeteer();
        Http::preventStrayRequests();
        Http::fake([
            'https://icon.example.com' => Http::response(
                '<html><head><link rel="apple-touch-icon" href="/apple-touch-icon.png"></head><body></body></html>'
            ),
            'https://icon.example.com/apple-touch-icon.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://icon.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('https://icon.example.com/apple-touch-icon.png', $signals->faviconUrl);
        $this->assertSame('https://icon.example.com/apple-touch-icon.png', $signals->logoPublicUrl);
        $this->assertFalse($signals->hasExactLogoSvg());
        $this->assertStringContainsString('using the site favicon as the header <img> src', $signals->summaryText);
        $this->assertStringContainsString('Site favicon URL (use as <link rel="icon">)', $signals->summaryText);

        if ($signals->logoImagePath !== null) {
            @unlink($signals->logoImagePath);
        }
    }

    public function test_scan_reads_a_shortcut_icon(): void
    {
        $this->fakeFailedPuppeteer();
        Http::preventStrayRequests();
        Http::fake([
            'https://shortcut.example.com' => Http::response(
                '<html><head><link href="/fav.ico" rel="shortcut icon"></head><body></body></html>'
            ),
            'https://shortcut.example.com/fav.ico' => Http::response(
                'ico',
                200,
                ['Content-Type' => 'image/x-icon'],
            ),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://shortcut.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('https://shortcut.example.com/fav.ico', $signals->faviconUrl);
        $this->assertSame('https://shortcut.example.com/fav.ico', $signals->logoPublicUrl);

        if ($signals->logoImagePath !== null) {
            @unlink($signals->logoImagePath);
        }
    }

    public function test_scan_uses_the_default_favicon_ico_when_no_icon_link_exists(): void
    {
        $this->fakeFailedPuppeteer();
        Http::preventStrayRequests();
        Http::fake([
            'https://default.example.com' => Http::response('<html><body><p>Hello</p></body></html>'),
            'https://default.example.com/favicon.ico' => Http::response(
                'ico',
                200,
                ['Content-Type' => 'image/x-icon'],
            ),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://default.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('https://default.example.com/favicon.ico', $signals->faviconUrl);
        $this->assertSame('https://default.example.com/favicon.ico', $signals->logoPublicUrl);

        if ($signals->logoImagePath !== null) {
            @unlink($signals->logoImagePath);
        }
    }

    public function test_scan_keeps_the_header_logo_and_still_records_the_favicon(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result(json_encode([
                'headerColor' => '#7c5cff',
                'colorSource' => 'cta',
                'headerBackground' => '#ffffff',
                'logo' => [
                    'kind' => 'img',
                    'src' => 'https://both.example.com/logo.png',
                ],
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://both.example.com' => Http::response(
                '<html><head><link rel="icon" href="/icon.svg"></head><body></body></html>'
            ),
            'https://both.example.com/logo.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
        ]);

        $signals = (new WebsiteBrandSignalExtractor)->scan('https://both.example.com');

        $this->assertNotNull($signals);
        $this->assertSame('https://both.example.com/logo.png', $signals->logoPublicUrl);
        $this->assertSame('https://both.example.com/icon.svg', $signals->faviconUrl);
        $this->assertStringContainsString('Public header logo URL', $signals->summaryText);
        $this->assertStringContainsString('https://both.example.com/icon.svg', $signals->summaryText);

        if ($signals->logoImagePath !== null) {
            @unlink($signals->logoImagePath);
        }
    }

    private function fakeFailedPuppeteer(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result('', 'chrome missing', 1),
        ]);
    }
}
