/**
 * @wrnexus/ui registry — SERVER-ONLY filesystem helpers for discovering the
 * package's `.wrn` component sources and stylesheet on disk.
 *
 * This is the code that used to live in `index.ts`. It was moved here
 * because it depends on `node:fs`/`node:path`/`node:url`, which don't exist
 * in a browser build — and `index.ts` is the package's main entry, so any
 * client-side (browser) bundle that reaches ANY `@wrnexus/ui` component
 * transitively tried to bundle this file too, failing with:
 *   "Browser polyfill for module 'node:url' doesn't have a matching export
 *    named 'fileURLToPath'"
 *
 * Import from `@wrnexus/ui/registry` (server-side code only — CLI,
 * dev-server, build). Never import this from a `.wrn` component or anything
 * that can end up in a client runtime bundle.
 */

import { readdirSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const here = dirname(fileURLToPath(import.meta.url));
const packageRoot = join(here, "..");
let cachedCss: string | undefined;
let cachedComponentFiles: Map<string, string> | undefined;

/** Absolute path to the directory of Wire UI component `.wrn` files. */
export function uiComponentsDir(): string {
  return join(packageRoot, "components");
}

/** Absolute path to the Wire UI stylesheet. */
export function uiCssPath(): string {
  return join(packageRoot, "ui.css");
}

/** The Wire UI stylesheet contents (all `.wire-*` classes, themed via tokens). */
export function uiCss(): string {
  return (cachedCss ??= readFileSync(uiCssPath(), "utf8"));
}

function uiComponentFiles(): Map<string, string> {
  if (cachedComponentFiles) return cachedComponentFiles;

  const files = new Map<string, string>();

  const componentFiles = readdirSync(uiComponentsDir()).filter((entry) => entry.endsWith(".wrn"));

  for (const file of componentFiles) {
    const path = join(uiComponentsDir(), file);
    const source = readFileSync(path, "utf8");
    const declaration = /^\s*component\s+([A-Za-z][A-Za-z0-9_]*)\b/m.exec(source);

    if (!declaration) {
      throw new Error(`UI component source does not declare a component: ${path}`);
    }

    const name = declaration[1]!;
    const previous = files.get(name);

    if (previous) {
      throw new Error(`Duplicate UI component declaration '${name}' in ${previous} and ${path}`);
    }

    files.set(name, path);
  }

  cachedComponentFiles = files;
  return files;
}

/** Names declared by the bundled components, independent of filename casing. */
export function uiComponentNames(): string[] {
  return [...uiComponentFiles().keys()].sort((left, right) => left.localeCompare(right));
}

/** Absolute path to a bundled component by its declared component name. */
export function uiComponentPath(name: string): string {
  const files = uiComponentFiles();
  const exact = files.get(name);
  if (exact) return exact;

  const normalized = name.toLowerCase();
  const matches = [...files.entries()].filter(
    ([componentName]) => componentName.toLowerCase() === normalized,
  );

  if (matches.length === 1) return matches[0]![1];
  throw new Error(`Unknown WRNexus UI component '${name}'.`);
}

export { uiComponentReference, findUiComponent, auditUiComponents } from "./metadata.ts";
export type { UiComponentMetadata, UiComponentReference } from "./metadata.ts";
