<?php
/**
 * globals.css manifest URL resolution (SPA shell / integrations).
 *
 * Loaded once from libs/assets.php via require_once.
 *
 * @package FleekDash
 */

declare(strict_types=1);

namespace FleekDash\Libs\Assets;

const GLOBALS_STYLES_RELATIVE_PATH = 'src/styles/globals.css';

const GLOBALS_VITE_ENTRY = 'globals';

const GLOBALS_FILENAME_NEEDLE = 'globals';

/**
 * @return string|null URL or null if not resolved from manifest scan
 */
function resolveGlobalsCssUrlFromManifest(object $manifest): ?string
{
    return resolveViteCssUrlFromManifest(
        $manifest,
        GLOBALS_VITE_ENTRY,
        GLOBALS_STYLES_RELATIVE_PATH,
        GLOBALS_FILENAME_NEEDLE,
    );
}

/**
 * Resolve globals stylesheet URL in development without serving raw src/styles/globals.css.
 *
 * Raw source contains Tailwind v4 @import "tailwindcss", which browsers resolve to
 * /src/styles/tailwindcss and return 404. Use Vite-processed CSS from the dev server when
 * available; if a dev manifest exists without origin, use the last production build from
 * manifest.json; on manifest errors, try manifest.json as well.
 *
 * @param string $manifest_dir Absolute path to the directory containing vite/manifest files
 */
function resolveGlobalsCssUrlDevelopment(string $manifest_dir): ?string
{
    $result = null;

    try {
        $manifest = getManifest($manifest_dir);
        $hasViteOrigin = $manifest->is_dev
            && isset($manifest->data->origin)
            && (string) $manifest->data->origin !== '';

        if ($hasViteOrigin) {
            $result = generateDevelopmentAssetSrc($manifest, GLOBALS_STYLES_RELATIVE_PATH);
        } elseif (!$manifest->is_dev) {
            $result = resolveGlobalsCssUrlFromManifest($manifest);
        } else {
            $result = resolveViteCssUrlFromProductionManifestFile(
                $manifest_dir,
                GLOBALS_VITE_ENTRY,
                GLOBALS_STYLES_RELATIVE_PATH,
                GLOBALS_FILENAME_NEEDLE,
            );
        }
    } catch (AssetManifestException) {
        $result = resolveViteCssUrlFromProductionManifestFile(
            $manifest_dir,
            GLOBALS_VITE_ENTRY,
            GLOBALS_STYLES_RELATIVE_PATH,
            GLOBALS_FILENAME_NEEDLE,
        );
    }

    return $result;
}

/**
 * Get the globals.css file with hash from manifest
 *
 * @param string $manifest_dir Manifest directory path (defaults to assets)
 *
 * @return string URL to the globals.css file with hash
 */
function getGlobalsCssUrl(string $manifest_dir = ''): string
{
    static $cache = null;

    if ($cache !== null) {
        return $cache;
    }

    if (empty($manifest_dir)) {
        $manifest_dir = FLEEKDASH_PLUGIN_DIR . ASSETS_DIRECTORY_NAME;
    }

    $resolved = null;

    if (isDevelopmentEnvironment()) {
        $resolved = resolveGlobalsCssUrlDevelopment($manifest_dir);
    } else {
        $manifest_path = $manifest_dir . '/' . MANIFEST_JSON_FILENAME;
        $manifest_exists = is_file($manifest_path) && is_readable($manifest_path);

        if ($manifest_exists) {
            try {
                $manifest = getManifest($manifest_dir);
                $resolved = resolveGlobalsCssUrlFromManifest($manifest);
            } catch (AssetManifestException $e) {
                $resolved = null;
            }
        }

        if ($resolved === null) {
            $resolved = resolveViteCssUrlFromGlobFallback($manifest_dir, GLOBALS_FILENAME_NEEDLE);
        }
    }

    if ($resolved === null) {
        $resolved = resolveViteCssUrlFromGlobFallback($manifest_dir, GLOBALS_FILENAME_NEEDLE);
    }

    if ($resolved === null) {
        $resolved = FLEEKDASH_PLUGIN_URL . GLOBALS_STYLES_RELATIVE_PATH;
    }

    $cache = $resolved;

    return $resolved;
}

function resolveGlobalsCssDiskPathProduction(): ?string
{
    $manifest_dir = FLEEKDASH_PLUGIN_DIR . ASSETS_DIRECTORY_NAME;

    return resolveViteCssDiskPathProduction(
        $manifest_dir,
        GLOBALS_VITE_ENTRY,
        GLOBALS_STYLES_RELATIVE_PATH,
        GLOBALS_FILENAME_NEEDLE,
    );
}

/**
 * Version for globals stylesheet enqueue (filemtime-based cache busting).
 */
function getGlobalsCssVersion(): string
{
    static $cached = null;

    if ($cached !== null) {
        return $cached;
    }

    $base = defined('FLEEKDASH_VERSION') ? \FLEEKDASH_VERSION : '1.0';
    $disk_path = null;

    if (isDevelopmentEnvironment()) {
        $candidate = FLEEKDASH_PLUGIN_DIR . GLOBALS_STYLES_RELATIVE_PATH;
        if (is_readable($candidate)) {
            $disk_path = $candidate;
        }
    } else {
        $disk_path = resolveGlobalsCssDiskPathProduction();

        if ($disk_path === null) {
            $fallback = FLEEKDASH_PLUGIN_DIR . GLOBALS_STYLES_RELATIVE_PATH;
            if (is_readable($fallback)) {
                $disk_path = $fallback;
            }
        }
    }

    $result = $base;
    if ($disk_path !== null) {
        $mtime = filemtime($disk_path);
        if ($mtime !== false) {
            $result .= '.' . (string) $mtime;
        }
    }

    $cached = $result;

    return $result;
}
