"""
FGIP SQLite Schema - Append-only knowledge graph tables.

All tables support:
- No DELETE operations (append-only)
- Status changes logged to edge_status_log
- SHA256 verification for sources
"""

SCHEMA_VERSION = "1.0.0"

CREATE_TABLES_SQL = """
-- Schema version tracking
CREATE TABLE IF NOT EXISTS schema_meta (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL,
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

-- Nodes: entities in the graph
CREATE TABLE IF NOT EXISTS nodes (
    node_id TEXT PRIMARY KEY,
    node_type TEXT NOT NULL,
    name TEXT NOT NULL,
    normalized_name TEXT NOT NULL,
    metadata TEXT,  -- JSON
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(node_type);
CREATE INDEX IF NOT EXISTS idx_nodes_normalized ON nodes(normalized_name);

-- Edges: relationships between nodes
-- assertion_level: FACT (proven), INFERENCE (plausible), HYPOTHESIS (spicy/private)
-- visibility: PRIVATE (internal only), PUBLIC (can be exported if assertion_level permits)
CREATE TABLE IF NOT EXISTS edges (
    edge_id TEXT PRIMARY KEY,
    edge_type TEXT NOT NULL,
    from_node_id TEXT NOT NULL,
    to_node_id TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'CLAIMED',  -- CLAIMED, EVIDENCED, DISPUTED, RETRACTED
    sensitivity TEXT NOT NULL DEFAULT 'LOW', -- LOW, MED, HIGH
    assertion_level TEXT NOT NULL DEFAULT 'INFERENCE',  -- FACT, INFERENCE, HYPOTHESIS
    visibility TEXT NOT NULL DEFAULT 'PRIVATE',  -- PRIVATE, PUBLIC
    confidence REAL,
    date_occurred_start TEXT,
    date_occurred_end TEXT,
    notes TEXT,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (from_node_id) REFERENCES nodes(node_id),
    FOREIGN KEY (to_node_id) REFERENCES nodes(node_id)
);
CREATE INDEX IF NOT EXISTS idx_edges_type ON edges(edge_type);
CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_node_id);
CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_node_id);
CREATE INDEX IF NOT EXISTS idx_edges_status ON edges(status);

-- Edge attributes: key-value pairs on edges
CREATE TABLE IF NOT EXISTS edge_attrs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    edge_id TEXT NOT NULL,
    key TEXT NOT NULL,
    value TEXT NOT NULL,
    value_type TEXT NOT NULL DEFAULT 'string',  -- string, int, float, json
    FOREIGN KEY (edge_id) REFERENCES edges(edge_id),
    UNIQUE (edge_id, key)
);
CREATE INDEX IF NOT EXISTS idx_edge_attrs_edge ON edge_attrs(edge_id);

-- Sources: evidence artifacts
CREATE TABLE IF NOT EXISTS sources (
    source_id TEXT PRIMARY KEY,
    source_type TEXT NOT NULL DEFAULT 'OTHER',
    title TEXT,
    author TEXT,
    publisher TEXT,
    date_published TEXT,
    date_accessed TEXT,
    url TEXT,
    file_path TEXT,  -- Relative to sources_dir
    sha256 TEXT,     -- Content hash
    tier INTEGER NOT NULL DEFAULT 2,  -- 0=primary, 1=secondary, 2=tertiary
    notes TEXT,
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_sources_type ON sources(source_type);
CREATE INDEX IF NOT EXISTS idx_sources_sha256 ON sources(sha256);

-- Edge-source links: which sources support which edges
CREATE TABLE IF NOT EXISTS edge_sources (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    edge_id TEXT NOT NULL,
    source_id TEXT NOT NULL,
    claim_excerpt TEXT,
    page_ref TEXT,
    added_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (edge_id) REFERENCES edges(edge_id),
    FOREIGN KEY (source_id) REFERENCES sources(source_id),
    UNIQUE (edge_id, source_id)
);
CREATE INDEX IF NOT EXISTS idx_edge_sources_edge ON edge_sources(edge_id);
CREATE INDEX IF NOT EXISTS idx_edge_sources_source ON edge_sources(source_id);

-- Claims: higher-level claims spanning multiple edges
CREATE TABLE IF NOT EXISTS claims (
    claim_id TEXT PRIMARY KEY,
    claim_text TEXT NOT NULL,
    claim_type TEXT NOT NULL DEFAULT 'OTHER',
    required_tier INTEGER NOT NULL DEFAULT 2,
    status TEXT NOT NULL DEFAULT 'CLAIMED',
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_claims_type ON claims(claim_type);
CREATE INDEX IF NOT EXISTS idx_claims_status ON claims(status);

-- Claim-edge links: which edges support which claims
CREATE TABLE IF NOT EXISTS claim_edges (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    claim_id TEXT NOT NULL,
    edge_id TEXT NOT NULL,
    FOREIGN KEY (claim_id) REFERENCES claims(claim_id),
    FOREIGN KEY (edge_id) REFERENCES edges(edge_id),
    UNIQUE (claim_id, edge_id)
);
CREATE INDEX IF NOT EXISTS idx_claim_edges_claim ON claim_edges(claim_id);
CREATE INDEX IF NOT EXISTS idx_claim_edges_edge ON claim_edges(edge_id);

-- Edge status log: append-only audit trail (NO DELETE)
CREATE TABLE IF NOT EXISTS edge_status_log (
    log_id TEXT PRIMARY KEY,
    edge_id TEXT NOT NULL,
    old_status TEXT NOT NULL,
    new_status TEXT NOT NULL,
    reason TEXT,
    actor TEXT,
    timestamp TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (edge_id) REFERENCES edges(edge_id)
);
CREATE INDEX IF NOT EXISTS idx_status_log_edge ON edge_status_log(edge_id);
CREATE INDEX IF NOT EXISTS idx_status_log_timestamp ON edge_status_log(timestamp);

-- Operation receipts: audit trail for all operations
CREATE TABLE IF NOT EXISTS operation_receipts (
    receipt_id TEXT PRIMARY KEY,
    operation TEXT NOT NULL,
    target_type TEXT NOT NULL,  -- node, edge, source, claim
    target_id TEXT NOT NULL,
    details TEXT,  -- JSON
    sha256 TEXT,   -- Hash of operation details
    timestamp TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_receipts_operation ON operation_receipts(operation);
CREATE INDEX IF NOT EXISTS idx_receipts_target ON operation_receipts(target_type, target_id);
"""


def init_schema(conn) -> dict:
    """
    Initialize the FGIP schema in the given SQLite connection.

    Returns a receipt dict with initialization details.
    """
    import hashlib
    import uuid
    from datetime import datetime

    cursor = conn.cursor()

    # Execute schema creation
    cursor.executescript(CREATE_TABLES_SQL)

    # Insert or update schema version
    cursor.execute("""
        INSERT OR REPLACE INTO schema_meta (key, value, updated_at)
        VALUES ('version', ?, datetime('now'))
    """, (SCHEMA_VERSION,))

    cursor.execute("""
        INSERT OR REPLACE INTO schema_meta (key, value, updated_at)
        VALUES ('initialized_at', datetime('now'), datetime('now'))
    """)

    conn.commit()

    # Build receipt
    schema_hash = hashlib.sha256(CREATE_TABLES_SQL.encode()).hexdigest()
    receipt_id = f"rcpt_{uuid.uuid4().hex[:16]}"

    receipt = {
        "receipt_id": receipt_id,
        "operation": "init_schema",
        "schema_version": SCHEMA_VERSION,
        "schema_sha256": schema_hash,
        "timestamp": datetime.utcnow().isoformat(),
        "tables_created": [
            "schema_meta", "nodes", "edges", "edge_attrs",
            "sources", "edge_sources", "claims", "claim_edges",
            "edge_status_log", "operation_receipts"
        ]
    }

    return receipt


def get_schema_version(conn) -> str:
    """Get the current schema version from the database."""
    cursor = conn.cursor()
    try:
        cursor.execute("SELECT value FROM schema_meta WHERE key = 'version'")
        row = cursor.fetchone()
        return row[0] if row else None
    except Exception:
        return None
