-- PSX Adventure Engine — Neon schema (GDD §9, Appendix B).
-- JSONB is used heavily so save shape and lobby settings can evolve without
-- a migration for every gameplay addition.

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TABLE IF NOT EXISTS users (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  username     TEXT UNIQUE NOT NULL,
  email        TEXT UNIQUE NOT NULL,
  display_name TEXT,
  created_at   TIMESTAMPTZ NOT NULL DEFAULT now(),
  last_login   TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS saves (
  id               UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id          UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  slot             INT NOT NULL,
  campaign         TEXT NOT NULL,
  title            TEXT,
  data             JSONB NOT NULL,
  playtime_seconds INT NOT NULL DEFAULT 0,
  updated_at       TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (user_id, slot, campaign)
);

CREATE INDEX IF NOT EXISTS saves_user_idx ON saves (user_id, updated_at DESC);

CREATE TABLE IF NOT EXISTS lobbies (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  code        TEXT UNIQUE NOT NULL,
  host_id     UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  status      TEXT NOT NULL DEFAULT 'waiting'
              CHECK (status IN ('waiting', 'starting', 'in_game', 'closed')),
  max_players INT NOT NULL DEFAULT 4,
  settings    JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
  expires_at  TIMESTAMPTZ NOT NULL DEFAULT now() + INTERVAL '4 hours'
);

-- Lobby codes are looked up on every join attempt; keep it cheap.
CREATE INDEX IF NOT EXISTS lobbies_open_idx
  ON lobbies (code) WHERE status <> 'closed';

CREATE TABLE IF NOT EXISTS lobby_players (
  lobby_id  UUID NOT NULL REFERENCES lobbies(id) ON DELETE CASCADE,
  user_id   UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  peer_id   INT NOT NULL,
  is_ready  BOOLEAN NOT NULL DEFAULT false,
  joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  PRIMARY KEY (lobby_id, user_id)
);
