//! kei-crossdomain EntitySchema — declarative spec consumed by
//! `kei_entity_store::Store` for migrations + user_version pragma.
//!
//! **Architectural note (2026-04-23 re-migration, Option B):**
//! kei-crossdomain is an edges-only graph store — URIs (`domain://path`)
//! are the only identifiers; there is no primary "node" entity row. The
//! engine's `EntitySchema` contract requires exactly one `IntegerPk`
//! field, so we declare a minimal synthetic `cross_nodes` table purely
//! to satisfy the DDL contract. No code writes to this table; every
//! query still runs against `cross_edges`.
//!
//! The rich `cross_edges` DDL is now generated by `kei-entity-store` via
//! `EdgeKeyKind::TextPairWithMetadata { from_col: "from_uri", to_col:
//! "to_uri", has_id, has_weight, has_created_at, extra_columns }`. The
//! legacy hand-rolled `custom_migrations` DDL was dropped; see git
//! history for the prior version.

use kei_entity_store::schema::{EdgeKeyKind, EntitySchema, FieldDef, FieldKind};
use rusqlite::{Connection, Result};

/// Synthetic primary table — exists solely to satisfy the engine's
/// `IntegerPk` requirement. Not used by any verb or caller.
static FIELDS: &[FieldDef] = &[FieldDef::pk("id")];

/// Extra columns on `cross_edges` beyond the standard metadata
/// (id / weight / created_at / edge_type). Defaults (`E4`, `{}`) are
/// applied by kei-crossdomain callers at INSERT time since the engine's
/// edge DDL only emits `TEXT DEFAULT ''` for `FieldKind::Text`; existing
/// databases keep their original `DEFAULT 'E4' / '{}'` column attributes
/// via SQLite's `CREATE TABLE IF NOT EXISTS` no-op.
static EDGE_EXTRAS: &[(&str, FieldKind)] = &[
    ("evidence", FieldKind::Text),
    ("metadata", FieldKind::Text),
];

pub static CROSSDOMAIN_SCHEMA: EntitySchema = EntitySchema {
    name: "crossdomain",
    table: "cross_nodes",
    fields: FIELDS,
    // Empty verb set: every kei-crossdomain op is bespoke (rich typed
    // edges with evidence/metadata — engine's `link` verb does dispatch
    // extras now, but kei-crossdomain keeps its own typed wrappers in
    // `edges.rs`/`bfs.rs`/`auto_link.rs` for the strongly-typed API).
    enabled_verbs: &[],
    fts_columns: None,
    edge_table: Some("cross_edges"),
    edge_key_kind: EdgeKeyKind::TextPairWithMetadata {
        from_col: "from_uri",
        to_col: "to_uri",
        has_id: true,
        has_weight: true,
        has_created_at: true,
        extra_columns: EDGE_EXTRAS,
    },
    archived_field: None,
    // Legacy hand-rolled DDL dropped — engine now emits it. Only the
    // kei-crossdomain-specific indexes (`idx_ce_from`, `idx_ce_type`)
    // live here; the engine auto-emits `idx_cross_edges_dst` on `to_uri`.
    custom_migrations: &[
        "CREATE INDEX IF NOT EXISTS idx_ce_from ON cross_edges(from_uri);",
        "CREATE INDEX IF NOT EXISTS idx_ce_type ON cross_edges(edge_type);",
    ],
};

/// Kept for backward compatibility with any external caller that
/// imported `schema::create_schema` directly. New code should open via
/// `Store::open` / `Store::open_memory`, which invokes the engine's
/// migration runner with `CROSSDOMAIN_SCHEMA`.
pub fn create_schema(conn: &Connection) -> Result<()> {
    // Delegate to the engine's DDL generator so the one-shot path stays
    // byte-identical to the engine-driven migration.
    let ddl = kei_entity_store::ddl::edge_table_for(
        "cross_edges",
        CROSSDOMAIN_SCHEMA.edge_key_kind,
    );
    conn.execute_batch(&ddl)?;
    for stmt in CROSSDOMAIN_SCHEMA.custom_migrations {
        conn.execute_batch(stmt)?;
    }
    Ok(())
}
