import { createHash } from "node:crypto";
import { existsSync, readFileSync } from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const assetManifest = readDashboardAssetManifest();
const bundleSources = new Map(assetManifest.bundles.map((bundle) => [bundle.name, bundle.sources]));
export function dashboardJs() {
    return readDashboardAsset("dashboard.js");
}
export function dashboardCss() {
    return readDashboardAsset("dashboard.css");
}
export function dashboardAssetVersion() {
    return createHash("sha256")
        .update(dashboardCss())
        .update("\n")
        .update(dashboardJs())
        .digest("hex")
        .slice(0, 12);
}
const staticAssetTypes = Object.fromEntries(assetManifest.staticAssets.map((asset) => [asset.name, asset.contentType]));
export function dashboardStaticAsset(assetName) {
    const contentType = staticAssetTypes[assetName];
    if (!contentType) {
        return null;
    }
    const filePath = dashboardStaticAssetPath(assetName);
    return filePath ? { filePath, contentType } : null;
}
export function dashboardBundleAsset(assetName) {
    const contentType = assetName === "dashboard.css" ? "text/css; charset=utf-8" : "application/javascript; charset=utf-8";
    const builtAsset = path.resolve(moduleDir, "..", "webui-assets", assetName);
    return existsSync(builtAsset) ? { filePath: builtAsset, contentType, ...compressedAssetPaths(builtAsset) } : null;
}
function readDashboardAsset(assetName) {
    const builtAsset = path.resolve(moduleDir, "..", "webui-assets", assetName);
    if (existsSync(builtAsset)) {
        return readFileSync(builtAsset, "utf8");
    }
    const sourceFiles = bundleSources.get(assetName);
    if (!sourceFiles) {
        throw new Error(`Dashboard asset manifest does not define ${assetName}`);
    }
    const sourceDir = path.join(moduleDir, "ui");
    const source = sourceFiles
        .map((file) => readFileSync(path.join(sourceDir, file), "utf8"))
        .join("\n");
    return assetName === "dashboard.js" ? transformDashboardJsSource(source) : source;
}
function readDashboardAssetManifest() {
    const builtManifest = path.resolve(moduleDir, "..", "webui-assets", "asset-manifest.json");
    const sourceManifest = path.join(moduleDir, "ui", "asset-manifest.json");
    const manifestPath = existsSync(builtManifest) ? builtManifest : sourceManifest;
    const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
    if (!Array.isArray(parsed.bundles) || !Array.isArray(parsed.staticAssets)) {
        throw new Error(`Invalid dashboard asset manifest: ${manifestPath}`);
    }
    return parsed;
}
function transformDashboardJsSource(source) {
    try {
        const { transformSync } = require("esbuild");
        const transformed = transformSync(source, {
            loader: "ts",
            format: "iife",
            legalComments: "none",
            minify: false,
            sourcefile: "dashboard.js",
            target: "es2022",
        }).code;
        return `${transformed}\n/* NordRelay dashboard source snapshot\n${source.replaceAll("*/", "* /")}\n*/\n`;
    }
    catch (error) {
        const detail = error instanceof Error ? error.message : String(error);
        throw new Error(`Dashboard source fallback requires esbuild. Run npm run build first. ${detail}`);
    }
}
function dashboardStaticAssetPath(assetName) {
    const builtAsset = path.resolve(moduleDir, "..", "webui-assets", assetName);
    if (existsSync(builtAsset)) {
        return builtAsset;
    }
    const sourceAsset = path.join(moduleDir, "ui", "assets", assetName);
    return existsSync(sourceAsset) ? sourceAsset : null;
}
function compressedAssetPaths(filePath) {
    return {
        brotliPath: existsSync(`${filePath}.br`) ? `${filePath}.br` : undefined,
        gzipPath: existsSync(`${filePath}.gz`) ? `${filePath}.gz` : undefined,
    };
}
