-- Phase 1 — Workstream A/E: the Architect's thesis substrate.
--
-- ADDITIVE AND REVERSIBLE ONLY (guardrail #3). Reversal: 0002_phase1_architect.down.sql.
-- Applied once by backend/core_migrations.py (schema_migrations ledger).
--
-- Models the "living messaging source of truth" as: multiple THESIS LINES (a core
-- spine + per-segment narratives), each a tree of typed NODES with full revision
-- history, frozen into immutable VERSIONS that a human signs off to make canonical.
-- Dual approval + collaborative text feedback live in thesis_reviews. Segments are
-- versioned defs that tie to the Phase-0 canonical_entities.segment pointer.

-- ============================================================================
-- thesis_lines — each distinct narrative line. is_core=1 is the shared spine;
-- others are segment-specific (Grant: different segments may carry different,
-- related thesis lines). Full-length ids (not the 8-char CRM ids).
-- ============================================================================
CREATE TABLE IF NOT EXISTS thesis_lines (
    id           TEXT PRIMARY KEY,        -- 'thl_' + uuid4 hex
    line_key     TEXT NOT NULL UNIQUE,    -- slug: 'core' | 'btc_native_hnwi' | ...
    name         TEXT NOT NULL,
    segment_key  TEXT,                    -- NULL for the core spine; else the segment this line serves
    is_core      INTEGER NOT NULL DEFAULT 0,
    description  TEXT,
    status       TEXT NOT NULL DEFAULT 'active',
    created_at   TEXT DEFAULT (datetime('now')),
    updated_at   TEXT DEFAULT (datetime('now')),
    deleted_at   TEXT
);

-- ============================================================================
-- thesis_nodes — typed node tree per line (the unit of iteration).
-- ============================================================================
CREATE TABLE IF NOT EXISTS thesis_nodes (
    id            TEXT PRIMARY KEY,       -- 'thn_' + uuid4 hex
    line_id       TEXT NOT NULL REFERENCES thesis_lines(id) ON DELETE CASCADE,
    parent_id     TEXT,                   -- tree edge; NULL for thesis_root
    node_type     TEXT NOT NULL,          -- thesis_root|throughline|section|claim|proof_point|objection|rebuttal|segment_cut
    ord           REAL NOT NULL DEFAULT 0,-- REAL so insert-between never renumbers siblings
    title         TEXT,
    body          TEXT,
    status        TEXT NOT NULL DEFAULT 'draft',   -- draft|candidate|approved|retired
    variant_group TEXT,                   -- nodes sharing this are competing phrasings of one idea (A/B)
    meta          TEXT,                   -- JSON: tone tags, confidence, evidence_refs -> canonical_entities/source ids
    created_at    TEXT DEFAULT (datetime('now')),
    updated_at    TEXT DEFAULT (datetime('now')),
    deleted_at    TEXT
);
CREATE INDEX IF NOT EXISTS idx_thesis_nodes_line   ON thesis_nodes(line_id);
CREATE INDEX IF NOT EXISTS idx_thesis_nodes_parent ON thesis_nodes(parent_id);
CREATE INDEX IF NOT EXISTS idx_thesis_nodes_variant ON thesis_nodes(variant_group);

-- ============================================================================
-- thesis_node_revisions — append-only per-node history (provenance + undo).
-- ============================================================================
CREATE TABLE IF NOT EXISTS thesis_node_revisions (
    id                TEXT PRIMARY KEY,
    node_id           TEXT NOT NULL,
    line_id           TEXT,
    rev_no            INTEGER NOT NULL,
    node_type         TEXT, title TEXT, body TEXT, status TEXT, ord REAL, variant_group TEXT, meta TEXT,
    change_summary    TEXT,
    change_reason     TEXT,               -- WHY the edit
    actor_type        TEXT,               -- human | agent
    actor_id          TEXT,               -- users.id or 'architect'
    claude_session_id TEXT,               -- ties an agent edit back to its reasoning session
    created_at        TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_thesis_revs_node ON thesis_node_revisions(node_id);

-- ============================================================================
-- thesis_versions — immutable named snapshots per line; ONE canonical per line.
-- body_json freezes the published artifact (the Architect->Scribe contract).
-- ============================================================================
CREATE TABLE IF NOT EXISTS thesis_versions (
    id                TEXT PRIMARY KEY,   -- 'thv_' + uuid4 hex
    line_id           TEXT NOT NULL REFERENCES thesis_lines(id) ON DELETE CASCADE,
    version_no        INTEGER NOT NULL,
    body_json         TEXT NOT NULL,      -- {throughline,pillars,claims,proof_points,segment_angles,voice,guardrails}
    status            TEXT NOT NULL DEFAULT 'draft',   -- draft|in_review|canonical|superseded
    rationale         TEXT,
    parent_version_id TEXT,
    created_by        TEXT,               -- users.id or 'architect'
    created_at        TEXT DEFAULT (datetime('now')),
    approved_at       TEXT,
    superseded_by     TEXT
);
CREATE INDEX IF NOT EXISTS idx_thesis_versions_line ON thesis_versions(line_id, version_no);
-- Hard invariant: at most one canonical version per line.
CREATE UNIQUE INDEX IF NOT EXISTS idx_thesis_one_canonical ON thesis_versions(line_id) WHERE status = 'canonical';

-- ============================================================================
-- thesis_reviews — dual approval + collaborative text feedback. Both partners
-- can comment/approve; the Architect ingests feedback to iterate. Promotion to
-- canonical happens when distinct 'approve' reviews meet the required count
-- (app_settings 'thesis_required_approvals', default 1) via the human route.
-- ============================================================================
CREATE TABLE IF NOT EXISTS thesis_reviews (
    id               TEXT PRIMARY KEY,
    version_id       TEXT NOT NULL REFERENCES thesis_versions(id) ON DELETE CASCADE,
    reviewer_user_id TEXT NOT NULL,       -- users.id (the human partner)
    decision         TEXT NOT NULL,       -- approve | request_changes | comment
    feedback         TEXT,                -- free-text the Architect reads to iterate
    target_node_id   TEXT,               -- optional: feedback scoped to one node
    created_at       TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_thesis_reviews_version ON thesis_reviews(version_id);

-- ============================================================================
-- segments — versioned LP segment definitions; one active per segment_key.
-- canonical_entities.segment (Phase 0) stores the segment_key pointer.
-- ============================================================================
CREATE TABLE IF NOT EXISTS segments (
    id            TEXT PRIMARY KEY,
    segment_key   TEXT NOT NULL,          -- slug
    name          TEXT NOT NULL,
    definition    TEXT,
    needs_to_hear TEXT,
    avoid         TEXT,
    version_no    INTEGER NOT NULL DEFAULT 1,
    status        TEXT NOT NULL DEFAULT 'active',   -- active | retired
    created_at    TEXT DEFAULT (datetime('now')),
    updated_at    TEXT DEFAULT (datetime('now'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_segments_one_active ON segments(segment_key) WHERE status = 'active';
