"""SQLite — the one local store for accounts, tokens (and later jobs, cache, usage).

Dependency-light by design (stdlib sqlite3). WAL mode so the API process and the
worker daemon can read/write concurrently without locking each other out. The DB
file (config.DB_PATH) is the ONE thing worth backing up — everything else
(artifact cache) is rebuildable. See SRE.md.
"""
import sqlite3
from contextlib import contextmanager

import config

SCHEMA = """
CREATE TABLE IF NOT EXISTS accounts (
    id      INTEGER PRIMARY KEY,
    name    TEXT UNIQUE NOT NULL,
    created REAL NOT NULL,
    notes   TEXT DEFAULT ''
);
CREATE TABLE IF NOT EXISTS tokens (
    id         INTEGER PRIMARY KEY,
    token_hash TEXT UNIQUE NOT NULL,   -- sha256(plaintext); plaintext never stored
    prefix     TEXT NOT NULL,          -- first chars of plaintext, for display only
    account_id INTEGER NOT NULL REFERENCES accounts(id),
    scopes     TEXT NOT NULL DEFAULT '',  -- space-separated; '*' = all engines
    quota_json TEXT,                    -- NULL = unlimited (used by #24)
    created    REAL NOT NULL,
    expires_at REAL,                    -- NULL = never
    revoked    INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_tokens_hash ON tokens(token_hash);
"""


def connect() -> sqlite3.Connection:
    config.DB_PATH.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(config.DB_PATH, timeout=10)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=ON")
    return conn


def init() -> None:
    with connect() as conn:
        conn.executescript(SCHEMA)


@contextmanager
def cursor():
    """Auto-init + commit/rollback context."""
    conn = connect()
    try:
        conn.executescript(SCHEMA)   # idempotent; cheap (IF NOT EXISTS)
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()
