-- +goose Up
-- Manual account blocking ("suspension"), the operator's hard counterpart to the soft,
-- reversible accounts.flagged_high_rate_at marker. Named "suspension" throughout the schema
-- and Go to stay distinct from the peer-to-peer `blocks` table (one player muting another);
-- the wire/UI vocabulary the player sees is "blocked". A suspension forces the player to
-- forfeit every active game and replaces their whole UI with a terminal "blocked" screen until
-- it is lifted or (for a temporary one) expires. See docs/ARCHITECTURE.md §12.
SET search_path = backend, pg_catalog;

-- The operator-editable reason picklist, one row per reason with its English and Russian text.
-- A suspension snapshots the chosen text (account_suspensions.reason_en/ru), so editing or
-- deleting a reason here never changes or breaks a reason already shown to a blocked player.
CREATE TABLE suspension_reasons (
    reason_id  uuid        PRIMARY KEY,
    text_en    text        NOT NULL,
    text_ru    text        NOT NULL,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now()
);

-- The block history: one row per block. blocked_until is NULL for a permanent block and the
-- expiry instant for a temporary one; lifted_at is stamped when an operator unblocks early.
-- reason_en/reason_ru are the text snapshot taken at block time (NULL when no reason was
-- cited); reason_id keeps a loose link to the picklist entry for later analytics and is nulled
-- if that entry is deleted (the snapshot remains the source of truth shown to the player). An
-- account is currently blocked when its newest row has lifted_at IS NULL AND (blocked_until IS
-- NULL OR blocked_until > now()).
CREATE TABLE account_suspensions (
    suspension_id uuid        PRIMARY KEY,
    account_id    uuid        NOT NULL REFERENCES accounts (account_id) ON DELETE CASCADE,
    blocked_at    timestamptz NOT NULL DEFAULT now(),
    blocked_until timestamptz,
    reason_en     text,
    reason_ru     text,
    reason_id     uuid        REFERENCES suspension_reasons (reason_id) ON DELETE SET NULL,
    lifted_at     timestamptz
);
-- The enforcement gate looks up the newest suspension for an account on every authenticated
-- request; this index serves that "latest by account" probe.
CREATE INDEX account_suspensions_account_idx ON account_suspensions (account_id, blocked_at DESC);

-- +goose Down
SET search_path = backend, pg_catalog;
DROP TABLE IF EXISTS account_suspensions;
DROP TABLE IF EXISTS suspension_reasons;
