CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, email_verified INTEGER NOT NULL DEFAULT 0, verification_token TEXT, verification_expires_at TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_users_username ON users(username); CREATE TABLE sessions ( id TEXT PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, expires_at TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX idx_sessions_user ON sessions(user_id); CREATE INDEX idx_sessions_expires ON sessions(expires_at); CREATE TABLE profiles ( user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE, display_name TEXT, avatar_path TEXT, bio TEXT, updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE TABLE games ( id INTEGER PRIMARY KEY AUTOINCREMENT, slug TEXT NOT NULL UNIQUE, name TEXT NOT NULL, category TEXT NOT NULL CHECK (category IN ('tabletop', 'casino')), max_players INTEGER NOT NULL DEFAULT 2, supports_multiplayer INTEGER NOT NULL DEFAULT 1 ); CREATE TABLE matches ( id INTEGER PRIMARY KEY AUTOINCREMENT, game_id INTEGER NOT NULL REFERENCES games(id), started_at TEXT NOT NULL DEFAULT (datetime('now')), ended_at TEXT, status TEXT NOT NULL DEFAULT 'in_progress' CHECK (status IN ('in_progress', 'completed', 'abandoned')) ); CREATE INDEX idx_matches_game ON matches(game_id); CREATE INDEX idx_matches_status ON matches(status); CREATE TABLE match_players ( match_id INTEGER NOT NULL REFERENCES matches(id) ON DELETE CASCADE, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, seat INTEGER NOT NULL, result TEXT CHECK (result IN ('win', 'loss', 'draw', 'abandoned')), score INTEGER, PRIMARY KEY (match_id, user_id) ); CREATE INDEX idx_match_players_user ON match_players(user_id);