-- ============================================================================
-- ctxd — Context Daemon Schema
-- SQLite 3.x, WAL mode, FTS5
-- (Legacy fallback for local dev when DATABASE_URL is not set)
-- ============================================================================

-- WAL for concurrent reads during writes; foreign keys enforced
PRAGMA journal_mode = WAL;
PRAGMA foreign_keys = ON;

-- ============================================================================
-- USERS
-- ============================================================================
CREATE TABLE users (
    user_id       TEXT PRIMARY KEY,
    display_name  TEXT NOT NULL,
    role          TEXT NOT NULL DEFAULT 'contributor'
                  CHECK (role IN ('admin', 'contributor', 'service')),
    token_hash    TEXT,
    active        INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
    created_at    TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    updated_at    TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

CREATE UNIQUE INDEX idx_users_lower ON users (LOWER(user_id));

-- ============================================================================
-- PROJECTS
-- ============================================================================
CREATE TABLE projects (
    project_id    TEXT PRIMARY KEY,
    display_name  TEXT NOT NULL,
    description   TEXT,
    metadata_tags TEXT DEFAULT '[]',
    shared_version INTEGER NOT NULL DEFAULT 0,
    auto_sync     INTEGER NOT NULL DEFAULT 0,
    sync_path     TEXT,
    created_at    TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    updated_at    TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

-- ============================================================================
-- PROJECT PERMISSIONS  (admin overrides all)
-- ============================================================================
CREATE TABLE project_permissions (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    project_id      TEXT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
    user_id         TEXT NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
    permission      TEXT NOT NULL DEFAULT 'editor'
                    CHECK (permission IN ('owner', 'editor', 'viewer')),
    UNIQUE(project_id, user_id)
);

-- ============================================================================
-- USER PROFILES  (personal context — timezone, preferences, style)
-- ============================================================================
CREATE TABLE user_profiles (
    user_id     TEXT PRIMARY KEY REFERENCES users(user_id) ON DELETE CASCADE,
    content     TEXT NOT NULL DEFAULT '',
    version     INTEGER NOT NULL DEFAULT 1,
    updated_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

-- ============================================================================
-- PROJECT CONTEXT  — THE AUTHORITATIVE SHARED COPY
-- ============================================================================
CREATE TABLE project_context (
    project_id     TEXT PRIMARY KEY REFERENCES projects(project_id) ON DELETE CASCADE,
    content        TEXT NOT NULL DEFAULT '',
    version        INTEGER NOT NULL DEFAULT 0,
    updated_by     TEXT REFERENCES users(user_id),
    updated_at     TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

-- ============================================================================
-- CONTEXT FILES  — individual files within a project
-- ============================================================================
CREATE TABLE context_files (
    file_id      INTEGER PRIMARY KEY AUTOINCREMENT,
    project_id   TEXT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
    file_path    TEXT NOT NULL,
    content      TEXT NOT NULL DEFAULT '',
    version      INTEGER NOT NULL DEFAULT 1,
    updated_by   TEXT REFERENCES users(user_id),
    updated_at   TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    UNIQUE(project_id, file_path)
);

-- ============================================================================
-- USER WORKSPACES  — per-user forks of a project
-- ============================================================================
CREATE TABLE user_workspaces (
    workspace_id   TEXT PRIMARY KEY,
    user_id        TEXT NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
    project_id     TEXT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
    status         TEXT NOT NULL DEFAULT 'in_progress'
                   CHECK (status IN ('in_progress', 'submitted', 'merged', 'abandoned')),
    base_version   INTEGER NOT NULL,
    current_version INTEGER NOT NULL DEFAULT 1,
    created_at     TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    updated_at     TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    UNIQUE(user_id, project_id, status)
);

-- ============================================================================
-- WORKSPACE FILES  — per-user fork of context_files
-- ============================================================================
CREATE TABLE workspace_files (
    file_id      INTEGER PRIMARY KEY AUTOINCREMENT,
    workspace_id TEXT NOT NULL REFERENCES user_workspaces(workspace_id) ON DELETE CASCADE,
    file_path    TEXT NOT NULL,
    content      TEXT NOT NULL DEFAULT '',
    version      INTEGER NOT NULL DEFAULT 1,
    updated_at   TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    UNIQUE(workspace_id, file_path)
);

-- ============================================================================
-- CHANGE REQUESTS  — submit / review / merge workflow
-- ============================================================================
CREATE TABLE change_requests (
    request_id       TEXT PRIMARY KEY,
    workspace_id     TEXT NOT NULL REFERENCES user_workspaces(workspace_id) ON DELETE CASCADE,
    project_id       TEXT NOT NULL REFERENCES projects(project_id),
    submitted_by     TEXT NOT NULL REFERENCES users(user_id),
    status           TEXT NOT NULL DEFAULT 'pending'
                     CHECK (status IN ('pending', 'approved', 'rejected', 'merged')),
    diff_summary     TEXT,
    target_version   INTEGER NOT NULL,
    base_version     INTEGER NOT NULL,
    created_at       TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    updated_at       TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

-- ============================================================================
-- REVIEWS  — approvals/rejections on change requests
-- ============================================================================
CREATE TABLE reviews (
    review_id    INTEGER PRIMARY KEY AUTOINCREMENT,
    request_id   TEXT NOT NULL REFERENCES change_requests(request_id) ON DELETE CASCADE,
    reviewer_id  TEXT NOT NULL REFERENCES users(user_id),
    decision     TEXT NOT NULL CHECK (decision IN ('approved', 'rejected')),
    comments     TEXT,
    created_at   TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    UNIQUE(request_id, reviewer_id)
);

-- ============================================================================
-- SNAPSHOTS  — point-in-time copies of project or workspace content
-- ============================================================================
CREATE TABLE snapshots (
    snapshot_id    TEXT PRIMARY KEY,
    project_id     TEXT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
    user_id        TEXT REFERENCES users(user_id) ON DELETE CASCADE,
    workspace_id   TEXT REFERENCES user_workspaces(workspace_id) ON DELETE SET NULL,
    version_from   INTEGER,
    version_to     INTEGER,
    storage_path   TEXT NOT NULL,
    content_hash   TEXT NOT NULL,
    size_bytes     INTEGER NOT NULL DEFAULT 0,
    created_at     TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

CREATE INDEX idx_snapshots_cleanup ON snapshots (project_id, user_id, created_at);

-- ============================================================================
-- AUDIT LOG  — append-only (INSERT only, never UPDATE or DELETE)
-- ============================================================================
CREATE TABLE audit_log (
    entry_id     INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id      TEXT NOT NULL REFERENCES users(user_id),
    agent_id     TEXT NOT NULL DEFAULT 'cli',
    session_id   TEXT,
    project_id   TEXT REFERENCES projects(project_id),
    operation    TEXT NOT NULL
                 CHECK (operation IN (
                     'read', 'update', 'create', 'delete',
                     'submit', 'approve', 'reject', 'merge',
                     'sync', 'search', 'export', 'restore',
                     'login', 'logout', 'import'
                 )),
    entity_type  TEXT,
    entity_id    TEXT,
    summary      TEXT NOT NULL,
    details_json TEXT,
    created_at   TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

CREATE INDEX idx_audit_user     ON audit_log (user_id, created_at);
CREATE INDEX idx_audit_project  ON audit_log (project_id, created_at);
CREATE INDEX idx_audit_agent    ON audit_log (agent_id, created_at);
CREATE INDEX idx_audit_op       ON audit_log (operation, created_at);

-- Trigger: audit_log is append-only
CREATE TRIGGER tr_audit_log_no_update
BEFORE UPDATE ON audit_log
BEGIN
    SELECT RAISE(ABORT, 'audit_log is append-only — no updates allowed');
END;

CREATE TRIGGER tr_audit_log_no_delete
BEFORE DELETE ON audit_log
BEGIN
    SELECT RAISE(ABORT, 'audit_log is append-only — no deletes allowed');
END;

-- ============================================================================
-- FULL-TEXT SEARCH  (FTS5)
-- ============================================================================
CREATE VIRTUAL TABLE fts_context USING fts5(
    content,
    project_id UNINDEXED,
    file_path UNINDEXED,
    source_type UNINDEXED,
    tokenize='porter unicode61'
);

-- Triggers to keep FTS index in sync with project_context
CREATE TRIGGER tr_fts_project_context_insert AFTER INSERT ON project_context
BEGIN
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.rowid, NEW.content, NEW.project_id, 'context.md', 'project_context');
END;

CREATE TRIGGER tr_fts_project_context_update AFTER UPDATE ON project_context
BEGIN
    DELETE FROM fts_context WHERE rowid = OLD.rowid;
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.rowid, NEW.content, NEW.project_id, 'context.md', 'project_context');
END;

CREATE TRIGGER tr_fts_project_context_delete AFTER DELETE ON project_context
BEGIN
    DELETE FROM fts_context WHERE rowid = OLD.rowid;
END;

-- Triggers for context_files
CREATE TRIGGER tr_fts_context_files_insert AFTER INSERT ON context_files
BEGIN
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.file_id + 1000000, NEW.content, NEW.project_id, NEW.file_path, 'context_file');
END;

CREATE TRIGGER tr_fts_context_files_update AFTER UPDATE ON context_files
BEGIN
    DELETE FROM fts_context WHERE rowid = OLD.file_id + 1000000;
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.file_id + 1000000, NEW.content, NEW.project_id, NEW.file_path, 'context_file');
END;

CREATE TRIGGER tr_fts_context_files_delete AFTER DELETE ON context_files
BEGIN
    DELETE FROM fts_context WHERE rowid = OLD.file_id + 1000000;
END;

-- Triggers for user_profiles
CREATE TRIGGER tr_fts_user_profiles_insert AFTER INSERT ON user_profiles
BEGIN
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.rowid + 2000000, NEW.content, '~user', NEW.user_id, 'user_profile');
END;

CREATE TRIGGER tr_fts_user_profiles_update AFTER UPDATE ON user_profiles
BEGIN
    DELETE FROM fts_context WHERE rowid = OLD.rowid + 2000000;
    INSERT INTO fts_context(rowid, content, project_id, file_path, source_type)
    VALUES (NEW.rowid + 2000000, NEW.content, '~user', NEW.user_id, 'user_profile');
END;

-- ============================================================================
-- SEED DATA  (for development / first-run)
-- ============================================================================
INSERT INTO users (user_id, display_name, role) VALUES
    ('admin', 'Administrator', 'admin'),
    ('hermes-gateway', 'Hermes Agent', 'service');

INSERT INTO projects (project_id, display_name, description) VALUES
    ('welcome', 'Welcome', 'Getting started guide and documentation for ctxd'),
    ('remote-rig', 'RemoteRig', 'Multi-camera remote monitoring system');

-- Project context is seeded by the Python init code (cmd_init)
-- to ensure real newlines, not literal backslash-n from SQL strings.