-- V030: Private club showcases. Adds club_memberships (member access control)
-- and replaces sessions.is_public with a 4-state publication_mode enum.
-- Backfills existing data: is_public=true → 'Both', is_public=false → 'None'.
-- portfolio_games gains the same enum (default 'Both' for pre-V030 rows).

-- 1. club_memberships
CREATE TABLE club_memberships (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    group_id        UUID NOT NULL REFERENCES game_groups(id) ON DELETE CASCADE,
    player_id       UUID NOT NULL REFERENCES players(id) ON DELETE CASCADE,
    status          VARCHAR(20) NOT NULL DEFAULT 'Pending'
                    CHECK (status IN ('Pending', 'Active', 'Rejected', 'Left')),
    role            VARCHAR(20) NOT NULL DEFAULT 'Member'
                    CHECK (role IN ('Member')),
    message         TEXT,
    applied_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    decided_at      TIMESTAMPTZ,
    decided_by      UUID REFERENCES players(id) ON DELETE SET NULL
);

-- Only one Active row per (group, player).
-- Re-application after Rejected/Left creates a new row.
CREATE UNIQUE INDEX ux_club_memberships_one_active
    ON club_memberships (group_id, player_id)
    WHERE status = 'Active';

CREATE INDEX ix_club_memberships_group_status
    ON club_memberships (group_id, status);

CREATE INDEX ix_club_memberships_player_status
    ON club_memberships (player_id, status);

-- 2. sessions.publication_mode (replaces is_public)
ALTER TABLE sessions
    ADD COLUMN publication_mode VARCHAR(20) NOT NULL DEFAULT 'None';

-- Backfill before constraint so existing data maps cleanly.
UPDATE sessions SET publication_mode = 'Both' WHERE is_public = true;
UPDATE sessions SET publication_mode = 'None' WHERE is_public = false;

ALTER TABLE sessions
    ADD CONSTRAINT ck_sessions_publication_mode
    CHECK (publication_mode IN ('None', 'Catalog', 'ClubOnly', 'Both'));

ALTER TABLE sessions DROP COLUMN is_public;

DROP INDEX IF EXISTS ix_sessions_public_schedule;
DROP INDEX IF EXISTS ix_sessions_showcase;

CREATE INDEX ix_sessions_public_schedule
    ON sessions (group_id, scheduled_at)
    WHERE publication_mode IN ('Catalog', 'Both') AND status <> 'Cancelled';

CREATE INDEX ix_sessions_showcase
    ON sessions (scheduled_at, system, is_one_shot, format)
    WHERE publication_mode IN ('Catalog', 'Both') AND status <> 'Cancelled';

-- 3. portfolio_games.publication_mode
-- Existing rows in portfolio_games keep 'Both' to stay visible to anonymous visitors.
ALTER TABLE portfolio_games
    ADD COLUMN publication_mode VARCHAR(20) NOT NULL DEFAULT 'Both'
    CHECK (publication_mode IN ('None', 'Catalog', 'ClubOnly', 'Both'));

CREATE INDEX ix_portfolio_games_showcase
    ON portfolio_games (created_at DESC)
    WHERE publication_mode IN ('Catalog', 'Both');
