-- All schema changes go into this file until 1.0.0 is tagged.
-- There will not be migrations during the early development phase.
-- After 1.0.0, new changes get their own numbered migration files.

-- Users: accounts and authentication
CREATE TABLE IF NOT EXISTS users (
    id TEXT PRIMARY KEY,                           -- UUID
    nick TEXT NOT NULL UNIQUE,
    password_hash TEXT NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_seen_at DATETIME
);

-- Auth tokens: one user can have multiple active tokens (multiple devices)
CREATE TABLE IF NOT EXISTS auth_tokens (
    token TEXT PRIMARY KEY,                        -- random token string
    user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    expires_at DATETIME,                           -- NULL = no expiry
    last_used_at DATETIME
);
CREATE INDEX IF NOT EXISTS idx_auth_tokens_user_id ON auth_tokens(user_id);

-- Channels: chat rooms
CREATE TABLE IF NOT EXISTS channels (
    id TEXT PRIMARY KEY,                           -- UUID
    name TEXT NOT NULL UNIQUE,                     -- #general, etc.
    topic TEXT NOT NULL DEFAULT '',
    modes TEXT NOT NULL DEFAULT '',                -- +i, +m, +s, +t, +n
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Channel members: who is in which channel, with per-user modes
CREATE TABLE IF NOT EXISTS channel_members (
    channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
    user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    modes TEXT NOT NULL DEFAULT '',                -- +o (operator), +v (voice)
    joined_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (channel_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_members_user_id ON channel_members(user_id);

-- Messages: channel and DM history (rotated per MAX_HISTORY)
CREATE TABLE IF NOT EXISTS messages (
    id TEXT PRIMARY KEY,                           -- UUID
    ts DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    from_user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    from_nick TEXT NOT NULL,                       -- denormalized for history
    target TEXT NOT NULL,                          -- #channel name or user UUID for DMs
    type TEXT NOT NULL DEFAULT 'message',          -- message, action, notice, join, part, quit, topic, mode, nick, system
    body TEXT NOT NULL DEFAULT '',
    meta TEXT NOT NULL DEFAULT '{}',               -- JSON extensible metadata
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_messages_target_ts ON messages(target, ts);
CREATE INDEX IF NOT EXISTS idx_messages_from_user ON messages(from_user_id);

-- Message queue: per-user pending delivery (unread messages)
CREATE TABLE IF NOT EXISTS message_queue (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
    queued_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(user_id, message_id)
);
CREATE INDEX IF NOT EXISTS idx_message_queue_user_id ON message_queue(user_id, queued_at);

-- Sessions: server-held session state
CREATE TABLE IF NOT EXISTS sessions (
    id TEXT PRIMARY KEY,                           -- UUID
    user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_active_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    expires_at DATETIME                            -- idle timeout
);
CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id);

-- Server links: federation peer configuration
CREATE TABLE IF NOT EXISTS server_links (
    id TEXT PRIMARY KEY,                           -- UUID
    name TEXT NOT NULL UNIQUE,                     -- human-readable peer name
    url TEXT NOT NULL,                             -- base URL of peer server
    shared_key_hash TEXT NOT NULL,                 -- hashed shared secret
    is_active INTEGER NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_seen_at DATETIME
);
