<?php

namespace App\Support\Filament;

use Illuminate\Support\Facades\Vite;

class PanelThemeAsset
{
    /**
     * @var array<string, bool>
     */
    private static array $hotAssetReachability = [];

    public static function resolve(string $entry): ?string
    {
        if (app()->runningUnitTests()) {
            return static::resolveFromManifest($entry);
        }

        if (static::shouldUseHotAsset($entry)) {
            return Vite::asset($entry);
        }

        return static::resolveFromManifest($entry);
    }

    private static function shouldUseHotAsset(string $entry): bool
    {
        $hotFile = public_path('hot');

        if (! is_file($hotFile)) {
            return false;
        }

        $hotUrl = trim((string) file_get_contents($hotFile));

        if ($hotUrl === '') {
            return false;
        }

        $assetUrl = Vite::asset($entry);

        if ($assetUrl === '') {
            return false;
        }

        if (array_key_exists($assetUrl, static::$hotAssetReachability)) {
            return static::$hotAssetReachability[$assetUrl];
        }

        $parts = parse_url($assetUrl);

        if (! is_array($parts)) {
            return static::$hotAssetReachability[$assetUrl] = false;
        }

        $host = $parts['host'] ?? null;

        if (! is_string($host) || $host === '') {
            return static::$hotAssetReachability[$assetUrl] = false;
        }

        $scheme = $parts['scheme'] ?? 'http';
        $port = $parts['port'] ?? ($scheme === 'https' ? 443 : 80);
        $transport = $scheme === 'https' ? 'ssl://' : '';
        $connection = @fsockopen($transport.$host, $port, $errorNumber, $errorMessage, 0.2);

        if (! is_resource($connection)) {
            return static::$hotAssetReachability[$assetUrl] = false;
        }

        $path = ($parts['path'] ?? '/').(isset($parts['query']) ? '?'.$parts['query'] : '');
        $hostHeader = isset($parts['port']) ? $host.':'.$port : $host;

        stream_set_timeout($connection, 0, 200000);
        fwrite(
            $connection,
            "HEAD {$path} HTTP/1.1\r\nHost: {$hostHeader}\r\nConnection: close\r\n\r\n",
        );

        $statusLine = fgets($connection);

        fclose($connection);

        if (! is_string($statusLine)) {
            return static::$hotAssetReachability[$assetUrl] = false;
        }

        return static::$hotAssetReachability[$assetUrl] = preg_match('/^HTTP\/\d\.\d\s+[23]\d\d\b/', $statusLine) === 1;
    }

    private static function resolveFromManifest(string $entry): ?string
    {
        $manifest = public_path('build/manifest.json');

        if (! is_file($manifest)) {
            return null;
        }

        /** @var array<string, array{file?: string}>|null $decoded */
        $decoded = json_decode((string) file_get_contents($manifest), true);

        if (! is_array($decoded)) {
            return null;
        }

        $file = $decoded[$entry]['file'] ?? null;

        if (! is_string($file) || $file === '') {
            return null;
        }

        return asset('build/'.$file);
    }
}
