<?php

namespace Tests\Unit\Services\AI;

use App\Models\PromptLandingPageAttachment;
use App\Services\AI\LaravelAiPromptLandingPageBriefResolver;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage;
use Laravel\Ai\StructuredAnonymousAgent;
use Tests\TestCase;

class LaravelAiPromptLandingPageBriefResolverTest extends TestCase
{
    public function test_inline_text_documents_keep_original_line_breaks(): void
    {
        Storage::fake('local');
        Storage::disk('local')->put(
            'prompt-landing-pages/1/notes.txt',
            "Headline:\nCustomer Proof\n\nFAQ",
        );

        StructuredAnonymousAgent::fake([
            $this->briefPayload(),
        ]);

        $attachment = new PromptLandingPageAttachment([
            'path' => 'prompt-landing-pages/1/notes.txt',
            'original_name' => 'notes.txt',
            'mime' => 'text/plain',
            'kind' => 'document',
        ]);

        (app(LaravelAiPromptLandingPageBriefResolver::class))->resolve(
            'Build this landing page.',
            [$attachment],
        );

        StructuredAnonymousAgent::assertPrompted(function ($prompt): bool {
            return str_contains($prompt->prompt, "Headline:\nCustomer Proof\n\nFAQ")
                && ! str_contains($prompt->prompt, 'Headline: Customer Proof FAQ');
        });
    }

    public function test_maps_logo_fields_from_the_structured_response(): void
    {
        StructuredAnonymousAgent::fake([
            $this->briefPayload([
                'logo_present' => true,
                'logo_type' => 'combination-mark',
                'logo_wordmark_text' => 'Austin Yoga',
                'logo_description' => 'A teal lotus icon beside the wordmark Austin Yoga.',
            ]),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Build this landing page.',
        );

        $this->assertTrue($brief->logoPresent);
        $this->assertSame('combination-mark', $brief->logoType);
        $this->assertSame('Austin Yoga', $brief->logoWordmarkText);
        $this->assertSame('A teal lotus icon beside the wordmark Austin Yoga.', $brief->logoDescription);
    }

    public function test_prefers_scanned_header_color_and_logo_url_over_the_model(): 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/logo.png',
                ],
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://lucos.example.com' => Http::response('<html></html>'),
            'https://lucos.example.com/logo.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
            'https://lucos.example.com/favicon.ico' => Http::response('', 404),
        ]);
        StructuredAnonymousAgent::fake([
            $this->briefPayload([
                'accent_color' => '#198754',
                'primary_color' => '#0d6efd',
                'logo_present' => false,
            ]),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Make a page for https://lucos.example.com',
        );

        $this->assertSame('#7c5cff', $brief->accentColor);
        $this->assertSame('#0d6efd', $brief->primaryColor);
        $this->assertSame('#ffffff', $brief->backgroundColor);
        $this->assertSame('#111111', $brief->textColor);
        $this->assertTrue($brief->logoPresent);
        $this->assertSame('https://lucos.example.com/logo.png', $brief->logoUrl);
        $this->assertSame('Inter', $brief->fontFamily);
        $this->assertSame(
            'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
            $brief->fontStylesheetUrl,
        );
    }

    public function test_uses_a_font_named_in_the_prompt_instead_of_the_scanned_website_font(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result(json_encode([
                'headerColor' => '#7c5cff',
                'colorSource' => 'cta',
                'headerBackground' => '#ffffff',
                'fontFamily' => 'Inter, sans-serif',
                'fontStylesheet' => 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
                'logo' => [
                    'kind' => 'img',
                    'src' => 'https://lucos.example.com/logo.png',
                ],
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://lucos.example.com' => Http::response('<html></html>'),
            'https://lucos.example.com/logo.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
            'https://lucos.example.com/favicon.ico' => Http::response('', 404),
        ]);
        StructuredAnonymousAgent::fake([
            $this->briefPayload(),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Make a page for https://lucos.example.com using the Playfair Display font.',
        );

        $this->assertSame('#7c5cff', $brief->accentColor);
        $this->assertSame('Playfair Display', $brief->fontFamily);
        $this->assertSame(
            'https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap',
            $brief->fontStylesheetUrl,
        );
    }

    public function test_uses_a_font_named_in_the_prompt_when_no_website_is_scanned(): void
    {
        StructuredAnonymousAgent::fake([
            $this->briefPayload(),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Build a yoga landing page using the Roboto font.',
        );

        $this->assertSame('Roboto', $brief->fontFamily);
        $this->assertSame(
            'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700&display=swap',
            $brief->fontStylesheetUrl,
        );
    }

    public function test_scans_the_saved_website_instead_of_a_url_in_the_prompt(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result(json_encode([
                'headerColor' => '#7c5cff',
                'colorSource' => 'cta',
                'headerBackground' => '#ffffff',
                'logo' => [
                    'kind' => 'img',
                    'src' => 'https://yoga.example.com/logo.png',
                ],
            ])),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://yoga.example.com' => Http::response('<html></html>'),
            'https://yoga.example.com/logo.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
            'https://yoga.example.com/favicon.ico' => Http::response('', 404),
        ]);
        StructuredAnonymousAgent::fake([
            $this->briefPayload([
                'accent_color' => '#198754',
                'logo_present' => false,
            ]),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Make a page for https://lucos.example.com',
            [],
            'https://yoga.example.com',
            'Promote studio memberships',
        );

        $this->assertSame('#7c5cff', $brief->accentColor);
        $this->assertSame('https://yoga.example.com/logo.png', $brief->logoUrl);
        $this->assertSame('Promote studio memberships', $brief->purpose);

        StructuredAnonymousAgent::assertPrompted(function ($prompt): bool {
            return str_contains($prompt->prompt, "Landing page purpose:\nPromote studio memberships")
                && str_contains($prompt->prompt, "Brand website to match:\nhttps://yoga.example.com");
        });
    }

    public function test_uses_the_scanned_favicon_as_the_logo_url_when_no_header_logo_exists(): void
    {
        Process::preventStrayProcesses();
        Process::fake([
            '*' => Process::result('', 'chrome missing', 1),
        ]);
        Http::preventStrayRequests();
        Http::fake([
            'https://icon.example.com' => Http::response(
                '<html><head><link rel="icon" href="https://icon.example.com/favicon-32.png"></head><body></body></html>'
            ),
            'https://icon.example.com/favicon-32.png' => Http::response(
                'png',
                200,
                ['Content-Type' => 'image/png'],
            ),
        ]);
        StructuredAnonymousAgent::fake([
            $this->briefPayload([
                'logo_present' => false,
            ]),
        ]);

        $brief = app(LaravelAiPromptLandingPageBriefResolver::class)->resolve(
            'Make a page for https://icon.example.com',
        );

        $this->assertTrue($brief->logoPresent);
        $this->assertSame('https://icon.example.com/favicon-32.png', $brief->logoUrl);
        $this->assertSame('https://icon.example.com/favicon-32.png', $brief->faviconUrl);

        StructuredAnonymousAgent::assertPrompted(function ($prompt): bool {
            return str_contains($prompt->prompt, 'Use this site favicon as the header <img> src')
                && str_contains($prompt->prompt, 'https://icon.example.com/favicon-32.png')
                && str_contains($prompt->prompt, 'The app injects this as <link rel="icon">');
        });
    }

    /**
     * @param  array<string, mixed>  $overrides
     * @return array<string, mixed>
     */
    private function briefPayload(array $overrides = []): array
    {
        return array_merge([
            'brand_name' => 'Austin Yoga',
            'offering' => 'Studio membership',
            'headline' => 'Find your calm in Austin',
            'features' => ['Small classes'],
            'benefits' => ['Less stress'],
            'pricing' => '$99 / month',
            'audience' => 'Busy professionals',
            'usps' => ['Downtown location'],
            'pain_points' => ['Crowded gyms'],
            'tone' => 'Calm and warm',
            'cta' => 'Book a class',
            'primary_color' => '#0f766e',
            'secondary_color' => '#14b8a6',
            'accent_color' => '#0d9488',
            'background_color' => '#f7fffc',
            'text_color' => '#0f172a',
            'logo_present' => false,
            'logo_type' => 'unknown',
            'logo_wordmark_text' => '',
            'logo_description' => '',
            'notes' => 'Earth tones',
        ], $overrides);
    }
}
