<?php

namespace Tests\Feature\Console;

use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class SyncGoogleFontsTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        config()->set('services.google_fonts.key', 'test-key');
    }

    public function test_it_downloads_fonts_and_writes_manifest(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'variants' => ['regular', '700'],
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                            '700' => 'https://fonts.gstatic.com/s/alpha-700.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'variants' => ['regular'],
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.ttf',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--count' => 2,
            '--weights' => '400,700',
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        $manifestPath = $targetPath.'/manifest.json';
        $cssPath = $targetPath.'/fonts.css';

        $this->assertFileExists($manifestPath);
        $this->assertFileExists($cssPath);

        $manifest = json_decode(File::get($manifestPath), true);
        $this->assertSame(2, $manifest['count']);
        $this->assertCount(2, $manifest['fonts']);

        $family = collect($manifest['fonts']);
        $this->assertTrue($family->pluck('family')->contains('Alpha Sans'));
        $this->assertTrue($family->pluck('family')->contains('Beta Serif'));

        $this->assertTrue(str_contains(File::get($cssPath), "font-family: 'Alpha Sans';"));
        $this->assertTrue(str_contains(File::get($cssPath), "font-family: 'Beta Serif';"));

        File::deleteDirectory($targetPath);
    }

    public function test_it_filters_by_category(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--count' => 5,
            '--category' => 'serif',
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        $manifestPath = $targetPath.'/manifest.json';
        $manifest = json_decode(File::get($manifestPath), true);

        $this->assertSame(1, $manifest['count']);
        $this->assertSame('Beta Serif', $manifest['fonts'][0]['family']);

        File::deleteDirectory($targetPath);
    }

    public function test_dry_run_does_not_write_files_or_download_fonts(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => function () {
                $this->fail('Font files should not be requested during dry run.');
            },
        ]);

        Artisan::call('fonts:sync-google', [
            '--count' => 1,
            '--path' => 'storage/app/test-fonts',
            '--dry-run' => true,
        ]);

        $this->assertDirectoryDoesNotExist($targetPath);
    }

    public function test_it_downloads_specific_family_even_when_count_is_smaller(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--count' => 1,
            '--family' => 'Beta Serif',
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        $manifestPath = $targetPath.'/manifest.json';
        $manifest = json_decode(File::get($manifestPath), true);

        $this->assertSame(1, $manifest['count']);
        $this->assertSame('Beta Serif', $manifest['fonts'][0]['family']);

        File::deleteDirectory($targetPath);
    }

    public function test_it_downloads_multiple_families_in_one_run(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--family' => 'Alpha Sans, Beta Serif',
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        $manifestPath = $targetPath.'/manifest.json';
        $manifest = json_decode(File::get($manifestPath), true);

        $this->assertSame(2, $manifest['count']);
        $this->assertCount(2, $manifest['fonts']);
        $this->assertTrue(collect($manifest['fonts'])->pluck('family')->contains('Alpha Sans'));
        $this->assertTrue(collect($manifest['fonts'])->pluck('family')->contains('Beta Serif'));

        File::deleteDirectory($targetPath);
    }

    public function test_it_merges_existing_manifest_when_syncing_single_family(): void
    {
        $targetPath = storage_path('app/test-fonts');
        File::deleteDirectory($targetPath);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--count' => 2,
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        Http::fake([
            'https://www.googleapis.com/webfonts/v1/webfonts*' => Http::response([
                'items' => [
                    [
                        'family' => 'Alpha Sans',
                        'category' => 'sans-serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/alpha-regular.woff2',
                        ],
                    ],
                    [
                        'family' => 'Beta Serif',
                        'category' => 'serif',
                        'files' => [
                            'regular' => 'https://fonts.gstatic.com/s/beta-regular.woff2',
                        ],
                    ],
                ],
            ]),
            'https://fonts.gstatic.com/*' => Http::response('font-binary', 200),
        ]);

        Artisan::call('fonts:sync-google', [
            '--family' => 'Alpha Sans',
            '--path' => 'storage/app/test-fonts',
            '--force' => true,
        ]);

        $manifestPath = $targetPath.'/manifest.json';
        $manifest = json_decode(File::get($manifestPath), true);

        $this->assertSame(2, $manifest['count']);
        $this->assertCount(2, $manifest['fonts']);
        $this->assertTrue(collect($manifest['fonts'])->pluck('family')->contains('Alpha Sans'));
        $this->assertTrue(collect($manifest['fonts'])->pluck('family')->contains('Beta Serif'));

        File::deleteDirectory($targetPath);
    }
}
