/**
 * Typed access to the buildbox host registry, the single source of host identity.
 *
 * The validating reader is `modules/workstation/claude/lib/buildbox-registry.mjs` and it
 * stays the only parser: this module imports it rather than reading the JSON, so a second
 * copy of the schema cannot drift from it. The import is dynamic because the collector's
 * tsconfig sets `allowJs: false` and includes only `src`.
 */

export interface RegistryHost {
  name: string;
  ssh_alias: string;
  state: "reachable" | "unreachable" | "bricked";
  machine_id: string | null;
  roles: readonly string[];
  access: Readonly<Record<string, string | null>>;
  rustdesk: string | null;
  notes: string;
}

export interface BuildboxRegistry {
  schema_version: 1;
  hosts: readonly RegistryHost[];
  orders: Readonly<Record<string, readonly string[]>>;
  source: string;
}

/** A registry that could not be read — never the same thing as a registry with no hosts. */
export class RegistryUnavailableError extends Error {
  constructor(detail: string) {
    super(`buildbox registry unavailable: ${detail}`);
    this.name = "RegistryUnavailableError";
  }
}

const MODULE_URL = new URL(
  "../../modules/workstation/claude/lib/buildbox-registry.mjs",
  import.meta.url,
).href;

type RegistryModule = { loadRegistry: (env?: NodeJS.ProcessEnv) => BuildboxRegistry };

export async function loadBuildboxRegistry(
  env: NodeJS.ProcessEnv = process.env,
): Promise<BuildboxRegistry> {
  let mod: RegistryModule;
  try {
    mod = (await import(/* @vite-ignore */ MODULE_URL)) as RegistryModule;
  } catch (err) {
    throw new RegistryUnavailableError(
      `cannot load the registry reader at ${MODULE_URL}: ${(err as Error).message}`,
    );
  }
  let registry: BuildboxRegistry;
  try {
    registry = mod.loadRegistry(env);
  } catch (err) {
    throw new RegistryUnavailableError((err as Error).message);
  }
  if (!Array.isArray(registry.hosts) || registry.hosts.length === 0) {
    throw new RegistryUnavailableError(
      `${registry.source} declares no hosts — the reader should have rejected this`,
    );
  }
  return registry;
}
