<?php

use App\Support\Filament\PanelThemeAsset;
use Illuminate\Support\Facades\File;

beforeEach(function (): void {
    $this->originalPublicPath = public_path();
    $this->originalEnvironment = app()->environment();
    $this->temporaryPublicPath = null;
});

afterEach(function (): void {
    app()->usePublicPath($this->originalPublicPath);
    app()->instance('env', $this->originalEnvironment);

    if (is_string($this->temporaryPublicPath) && File::isDirectory($this->temporaryPublicPath)) {
        File::deleteDirectory($this->temporaryPublicPath);
    }
});

function useTemporaryPublicPath(): string
{
    $path = sys_get_temp_dir().'/panel-theme-asset-'.bin2hex(random_bytes(8));

    File::ensureDirectoryExists($path);
    app()->usePublicPath($path);
    test()->temporaryPublicPath = $path;

    return $path;
}

it('returns null when no build manifest or hot file exists', function (): void {
    useTemporaryPublicPath();

    expect(PanelThemeAsset::resolve('resources/css/filament/admin/theme.css'))->toBeNull();
});

it('resolves compiled theme assets from the build manifest', function (): void {
    $publicPath = useTemporaryPublicPath();

    File::ensureDirectoryExists($publicPath.'/build');
    File::put(
        $publicPath.'/build/manifest.json',
        json_encode([
            'resources/css/filament/admin/theme.css' => [
                'file' => 'assets/theme-test.css',
            ],
        ], JSON_THROW_ON_ERROR),
    );

    expect(PanelThemeAsset::resolve('resources/css/filament/admin/theme.css'))
        ->toEndWith('/build/assets/theme-test.css');
});

it('ignores the Vite hot file during tests and still resolves the built manifest asset', function (): void {
    $publicPath = useTemporaryPublicPath();

    File::ensureDirectoryExists($publicPath.'/build');
    File::put($publicPath.'/hot', 'http://localhost:5173');
    File::put(
        $publicPath.'/build/manifest.json',
        json_encode([
            'resources/css/filament/admin/theme.css' => [
                'file' => 'assets/theme-test.css',
            ],
        ], JSON_THROW_ON_ERROR),
    );

    expect(PanelThemeAsset::resolve('resources/css/filament/admin/theme.css'))
        ->toEndWith('/build/assets/theme-test.css')
        ->not->toContain(':5173');
});

it('falls back to the built manifest asset when the Vite hot server is unreachable', function (): void {
    $publicPath = useTemporaryPublicPath();

    app()->instance('env', 'local');

    File::ensureDirectoryExists($publicPath.'/build');
    File::put($publicPath.'/hot', 'http://127.0.0.1:1');
    File::put(
        $publicPath.'/build/manifest.json',
        json_encode([
            'resources/css/filament/admin/theme.css' => [
                'file' => 'assets/theme-test.css',
            ],
        ], JSON_THROW_ON_ERROR),
    );

    expect(PanelThemeAsset::resolve('resources/css/filament/admin/theme.css'))
        ->toEndWith('/build/assets/theme-test.css')
        ->not->toContain(':1');
});

it('returns null when the build manifest contains invalid json', function (): void {
    $publicPath = useTemporaryPublicPath();

    File::ensureDirectoryExists($publicPath.'/build');
    File::put($publicPath.'/build/manifest.json', '{invalid-json');

    expect(PanelThemeAsset::resolve('resources/css/filament/admin/theme.css'))->toBeNull();
});
