/**
 * Composed entity-type registry view.
 *
 * Glues together:
 *   1. `ENTITY_SCHEMAS` (baseline schemas in `schema_definitions.ts`)
 *   2. `BASELINE_VERTICAL_METADATA` (vertical assignments for baseline types)
 *   3. Vertical-pack schema manifests under `src/services/verticals/schemas/`
 *      (vertical-specific entity types)
 *
 * Consumers:
 *   - `GET /api/registry/entity-types` (P2 API endpoint)
 *   - `scripts/generate_frontend_entity_types.ts` (P2 generator) emitting
 *     `frontend/src/data/entity_types.generated.ts`
 *   - records-index/records-guide pages on the marketing site (P2 frontend)
 *
 * The composed view is intentionally read-only and side-effect-free so it
 * can be consumed both at runtime (via the API) and at build time (via the
 * generator) without booting the database.
 */
import { existsSync, readFileSync } from "node:fs";
import { isAbsolute, join } from "node:path";
import { config } from "../../config.js";
import { ENTITY_SCHEMAS } from "../schema_definitions.js";
import { BASELINE_VERTICAL_METADATA, } from "./baseline_metadata.js";
import { VERTICAL_PACKS, findVerticalPack, } from "./registry.js";
function projectRoot() {
    return config.projectRoot;
}
function resolveManifestPath(pack) {
    if (!pack.schema_manifest_path)
        return null;
    return isAbsolute(pack.schema_manifest_path)
        ? pack.schema_manifest_path
        : join(projectRoot(), pack.schema_manifest_path);
}
function readPackManifest(pack) {
    const path = resolveManifestPath(pack);
    if (!path || !existsSync(path))
        return null;
    try {
        const raw = readFileSync(path, "utf8");
        return JSON.parse(raw);
    }
    catch (err) {
        process.stderr.write(`[entity-type-registry] Failed to load ${pack.slug} manifest: ${err.message}\n`);
        return null;
    }
}
function entryFromBaseline(entity_type, baseline) {
    const schema = ENTITY_SCHEMAS[entity_type];
    return {
        entity_type,
        label: schema?.metadata?.label ?? entity_type,
        description: schema?.metadata?.description ?? "",
        category: schema?.metadata?.category ?? "knowledge",
        verticals: [...baseline.verticals],
        primary_vertical: baseline.primary_vertical,
        example_use_case: baseline.example_use_case,
        provenance: "baseline_map",
        aliases: schema?.metadata?.aliases,
    };
}
function entryFromBaselineSchemaOnly(entity_type) {
    const schema = ENTITY_SCHEMAS[entity_type];
    return {
        entity_type,
        label: schema?.metadata?.label ?? entity_type,
        description: schema?.metadata?.description ?? "",
        category: schema?.metadata?.category ?? "knowledge",
        verticals: schema?.metadata?.verticals
            ? [...schema.metadata.verticals]
            : [],
        primary_vertical: schema?.metadata?.primary_vertical,
        example_use_case: schema?.metadata?.example_use_case,
        provenance: schema?.metadata?.verticals?.length
            ? "schema_metadata"
            : "unmapped",
        aliases: schema?.metadata?.aliases,
    };
}
function entryFromPack(entity_type, pack, manifestEntry) {
    const meta = manifestEntry.metadata ?? {
        label: entity_type,
        description: "",
        category: "knowledge",
    };
    const verticals = meta.verticals?.length
        ? meta.verticals
        : meta.primary_vertical
            ? [meta.primary_vertical]
            : [pack.slug];
    return {
        entity_type,
        label: meta.label ?? entity_type,
        description: meta.description ?? "",
        category: meta.category ?? "knowledge",
        verticals: [...verticals],
        primary_vertical: meta.primary_vertical ?? pack.slug,
        example_use_case: meta.example_use_case,
        provenance: "vertical_pack",
        source_pack_slug: pack.slug,
    };
}
/** Build the composed registry view. Pure (no DB access). */
export function buildEntityTypeRegistryPayload() {
    const entries = [];
    const seen = new Set();
    for (const pack of VERTICAL_PACKS) {
        const manifest = readPackManifest(pack);
        if (!manifest)
            continue;
        for (const entry of manifest.schemas) {
            if (seen.has(entry.entity_type))
                continue;
            seen.add(entry.entity_type);
            entries.push(entryFromPack(entry.entity_type, pack, entry));
        }
    }
    for (const [entity_type, baseline] of Object.entries(BASELINE_VERTICAL_METADATA)) {
        if (seen.has(entity_type))
            continue;
        seen.add(entity_type);
        entries.push(entryFromBaseline(entity_type, baseline));
    }
    for (const entity_type of Object.keys(ENTITY_SCHEMAS)) {
        if (seen.has(entity_type))
            continue;
        seen.add(entity_type);
        entries.push(entryFromBaselineSchemaOnly(entity_type));
    }
    entries.sort((a, b) => a.entity_type.localeCompare(b.entity_type));
    const by_vertical = {};
    for (const pack of VERTICAL_PACKS) {
        by_vertical[pack.slug] = [];
    }
    for (const entry of entries) {
        for (const slug of entry.verticals) {
            const pack = findVerticalPack(slug);
            const canonical = pack?.slug ?? slug;
            if (!by_vertical[canonical])
                by_vertical[canonical] = [];
            if (!by_vertical[canonical].includes(entry.entity_type)) {
                by_vertical[canonical].push(entry.entity_type);
            }
        }
    }
    for (const slug of Object.keys(by_vertical)) {
        by_vertical[slug].sort();
    }
    return {
        generated_at: new Date().toISOString(),
        entity_type_count: entries.length,
        entries,
        by_vertical,
    };
}
/** Lookup a single entity type's registry entry by its (canonical) slug. */
export function getEntityTypeRegistryEntry(entity_type) {
    const payload = buildEntityTypeRegistryPayload();
    return payload.entries.find((e) => e.entity_type === entity_type) ?? null;
}
/** Entity types declared as native to a given vertical slug. */
export function listEntityTypesForVertical(slug) {
    const payload = buildEntityTypeRegistryPayload();
    const pack = findVerticalPack(slug);
    const canonical = pack?.slug ?? slug;
    return payload.by_vertical[canonical] ?? [];
}
//# sourceMappingURL=entity_type_registry.js.map