-- +goose Up
-- Initial schema for the Scrabble backend service: durable accounts, their
-- platform/email identities, and opaque server sessions.
--
-- Every backend table lives in the `backend` schema. The schema is created here
-- so a fresh database can apply this migration, and search_path is pinned for
-- the rest of the migration so the CREATE statements land in `backend` without
-- qualifying every object. Production also pins search_path via
-- BACKEND_POSTGRES_DSN.
CREATE SCHEMA IF NOT EXISTS backend;
SET search_path = backend, pg_catalog;

-- Durable internal accounts. Guests are session-only and never reach this table.
CREATE TABLE accounts (
    account_id            uuid        PRIMARY KEY,
    display_name          text        NOT NULL DEFAULT '',
    preferred_language    text        NOT NULL DEFAULT 'en',
    time_zone             text        NOT NULL DEFAULT 'UTC',
    block_chat            boolean     NOT NULL DEFAULT false,
    block_friend_requests boolean     NOT NULL DEFAULT false,
    created_at            timestamptz NOT NULL DEFAULT now(),
    updated_at            timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT accounts_preferred_language_chk CHECK (preferred_language IN ('en', 'ru'))
);

-- Platform and email identities attached to an account. external_id is the
-- platform user id (kind='telegram') or the email address (kind='email');
-- confirmed flips true once an email confirm-code is verified (later stages).
CREATE TABLE identities (
    identity_id uuid        PRIMARY KEY,
    account_id  uuid        NOT NULL REFERENCES accounts (account_id) ON DELETE CASCADE,
    kind        text        NOT NULL,
    external_id text        NOT NULL,
    confirmed   boolean     NOT NULL DEFAULT false,
    created_at  timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT identities_kind_chk CHECK (kind IN ('telegram', 'email')),
    CONSTRAINT identities_kind_external_id_key UNIQUE (kind, external_id)
);
CREATE INDEX identities_account_idx ON identities (account_id);

-- Opaque server sessions. token_hash is the hex-encoded SHA-256 of the bearer
-- token; the plaintext token is never stored. Sessions are revoke-only (no
-- TTL): status moves active -> revoked and revoked_at is stamped.
CREATE TABLE sessions (
    session_id   uuid        PRIMARY KEY,
    account_id   uuid        NOT NULL REFERENCES accounts (account_id) ON DELETE CASCADE,
    token_hash   text        NOT NULL,
    status       text        NOT NULL DEFAULT 'active',
    created_at   timestamptz NOT NULL DEFAULT now(),
    last_seen_at timestamptz,
    revoked_at   timestamptz,
    CONSTRAINT sessions_status_chk CHECK (status IN ('active', 'revoked')),
    CONSTRAINT sessions_token_hash_key UNIQUE (token_hash)
);
CREATE INDEX sessions_account_idx ON sessions (account_id);

-- +goose Down
DROP TABLE sessions;
DROP TABLE identities;
DROP TABLE accounts;
