"""
cortex/storage/migrations/v8_schema_foundations.py — Schema foundations for v3.2 sleep-gated layers.

Adds additive schema primitives needed for wake/sleep/handoff flow:
- semantic_claim.intrinsic_type
- semantic_claim.human_family
- memory_activation
- memory_evidence
- handoff_packet
- open_loop
- commitment

Also backfills intrinsic_type from existing semantic_claim.category values.

Migration: version 7 → 8
"""

VERSION = 8
DESCRIPTION = "Add v3.2 schema foundations: activation, evidence, handoff, loops, commitments"

SQL_UP = """
ALTER TABLE semantic_claim ADD COLUMN intrinsic_type TEXT DEFAULT NULL;
ALTER TABLE semantic_claim ADD COLUMN human_family TEXT DEFAULT NULL;

CREATE INDEX IF NOT EXISTS idx_claim_intrinsic_type
    ON semantic_claim (owner_id, intrinsic_type, status);
CREATE INDEX IF NOT EXISTS idx_claim_human_family
    ON semantic_claim (owner_id, human_family, status);

UPDATE semantic_claim
SET intrinsic_type = CASE category
    WHEN 'identity' THEN 'fact'
    WHEN 'personal' THEN 'fact'
    WHEN 'preferences' THEN 'preference'
    WHEN 'engineering' THEN 'fact'
    WHEN 'goals' THEN 'goal'
    WHEN 'misc' THEN 'fact'
    ELSE 'fact'
END
WHERE intrinsic_type IS NULL;

-- -----------------------------------------------------------------------
-- memory_activation: retrieval/activation policy attached to claims
-- -----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS memory_activation (
    id                TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    owner_id          TEXT NOT NULL DEFAULT 'default',
    claim_id          TEXT NOT NULL,
    scope             TEXT NOT NULL DEFAULT 'session',
    trigger_pattern   TEXT,
    suppressors_json  TEXT DEFAULT '[]',
    priority          INTEGER DEFAULT 0,
    decay_factor      REAL DEFAULT 1.0,
    created_at        TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at        TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (claim_id) REFERENCES semantic_claim(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_memact_owner ON memory_activation(owner_id);
CREATE INDEX IF NOT EXISTS idx_memact_claim ON memory_activation(claim_id);
CREATE INDEX IF NOT EXISTS idx_memact_scope_priority
    ON memory_activation(owner_id, scope, priority);

-- -----------------------------------------------------------------------
-- memory_evidence: link semantic claims back to episode evidence
-- -----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS memory_evidence (
    id                TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    owner_id          TEXT NOT NULL DEFAULT 'default',
    claim_id          TEXT NOT NULL,
    episode_event_id  TEXT NOT NULL,
    evidence_role     TEXT DEFAULT 'support',
    excerpt_text      TEXT,
    confidence        REAL DEFAULT 1.0,
    created_at        TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (claim_id) REFERENCES semantic_claim(id) ON DELETE CASCADE,
    FOREIGN KEY (episode_event_id) REFERENCES episode_event(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_mev_owner ON memory_evidence(owner_id);
CREATE INDEX IF NOT EXISTS idx_mev_claim ON memory_evidence(claim_id);
CREATE INDEX IF NOT EXISTS idx_mev_episode ON memory_evidence(episode_event_id);

-- -----------------------------------------------------------------------
-- handoff_packet: session boundary summaries / resumable handoffs
-- -----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS handoff_packet (
    id                TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    owner_id          TEXT NOT NULL DEFAULT 'default',
    session_id        TEXT,
    status            TEXT NOT NULL DEFAULT 'active',
    summary_text      TEXT,
    payload_json      TEXT DEFAULT '{}',
    generated_at      TEXT,
    consumed_at       TEXT,
    created_at        TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at        TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (session_id) REFERENCES session_record(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS idx_handoff_owner_status
    ON handoff_packet(owner_id, status, created_at);
CREATE INDEX IF NOT EXISTS idx_handoff_session ON handoff_packet(session_id);

-- -----------------------------------------------------------------------
-- open_loop: unresolved threads / promises / follow-ups
-- -----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS open_loop (
    id                TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    owner_id          TEXT NOT NULL DEFAULT 'default',
    session_id        TEXT,
    claim_id          TEXT,
    title             TEXT NOT NULL,
    description       TEXT,
    status            TEXT NOT NULL DEFAULT 'open',
    priority          INTEGER DEFAULT 0,
    due_at            TEXT,
    resolved_at       TEXT,
    created_at        TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at        TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (session_id) REFERENCES session_record(id) ON DELETE SET NULL,
    FOREIGN KEY (claim_id) REFERENCES semantic_claim(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS idx_open_loop_owner_status
    ON open_loop(owner_id, status, priority);
CREATE INDEX IF NOT EXISTS idx_open_loop_session ON open_loop(session_id);
CREATE INDEX IF NOT EXISTS idx_open_loop_claim ON open_loop(claim_id);

-- -----------------------------------------------------------------------
-- commitment: explicit obligations / promises tracked across sessions
-- -----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS commitment (
    id                TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    owner_id          TEXT NOT NULL DEFAULT 'default',
    session_id        TEXT,
    claim_id          TEXT,
    title             TEXT NOT NULL,
    description       TEXT,
    status            TEXT NOT NULL DEFAULT 'active',
    strength          REAL DEFAULT 1.0,
    due_at            TEXT,
    completed_at      TEXT,
    created_at        TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at        TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (session_id) REFERENCES session_record(id) ON DELETE SET NULL,
    FOREIGN KEY (claim_id) REFERENCES semantic_claim(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS idx_commitment_owner_status
    ON commitment(owner_id, status, due_at);
CREATE INDEX IF NOT EXISTS idx_commitment_session ON commitment(session_id);
CREATE INDEX IF NOT EXISTS idx_commitment_claim ON commitment(claim_id);
"""

# SQLite downgrade is intentionally partial/no-op here because DROP COLUMN remains
# awkward across versions and these are additive foundations. Operators needing a
# hard rollback should restore from backup.
SQL_DOWN = """
DROP INDEX IF EXISTS idx_commitment_claim;
DROP INDEX IF EXISTS idx_commitment_session;
DROP INDEX IF EXISTS idx_commitment_owner_status;
DROP TABLE IF EXISTS commitment;

DROP INDEX IF EXISTS idx_open_loop_claim;
DROP INDEX IF EXISTS idx_open_loop_session;
DROP INDEX IF EXISTS idx_open_loop_owner_status;
DROP TABLE IF EXISTS open_loop;

DROP INDEX IF EXISTS idx_handoff_session;
DROP INDEX IF EXISTS idx_handoff_owner_status;
DROP TABLE IF EXISTS handoff_packet;

DROP INDEX IF EXISTS idx_mev_episode;
DROP INDEX IF EXISTS idx_mev_claim;
DROP INDEX IF EXISTS idx_mev_owner;
DROP TABLE IF EXISTS memory_evidence;

DROP INDEX IF EXISTS idx_memact_scope_priority;
DROP INDEX IF EXISTS idx_memact_claim;
DROP INDEX IF EXISTS idx_memact_owner;
DROP TABLE IF EXISTS memory_activation;

-- semantic_claim columns remain in place on downgrade.
DROP INDEX IF EXISTS idx_claim_human_family;
DROP INDEX IF EXISTS idx_claim_intrinsic_type;
SELECT 1;
"""
