CREATE TABLE IF NOT EXISTS guilds (
    id BIGINT PRIMARY KEY NOT NULL,
    name TEXT,
    owner_id BIGINT,
    volume INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS dice_track (
    id UUID PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
    guild_id BIGINT NOT NULL,
    owner_id BIGINT NOT NULL,
    dice TEXT NOT NULL,
    user_id BIGINT,
    value INT,
    operator TEXT
);
CREATE TABLE IF NOT EXISTS events (
    id UUID PRIMARY KEY NOT NULL,
    guild_id BIGINT NOT NULL,
    author_id BIGINT NOT NULL,
    title TEXT NOT NULL,
    date_time TIMESTAMP NOT NULL,
    description TEXT,
    rsvp BIGINT[] NOT NULL
);
CREATE TABLE IF NOT EXISTS races (
    id INTEGER GENERATED ALWAYS AS IDENTITY,
    name TEXT NOT NULL,
    size TEXT NOT NULL,
    source TEXT NOT NULL,
    data JSON NOT NULL
);
CREATE TABLE IF NOT EXISTS classes (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS feats (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS options_features (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS backgrounds (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS items (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS spells (
    id INTEGER GENERATED ALWAYS AS IDENTITY,
    name TEXT NOT NULL,
    school TEXT NOT NULL,
    level INTEGER NOT NULL,
    ritual BOOLEAN DEFAULT FALSE,
    concentration BOOLEAN DEFAULT FALSE,
    classes TEXT[] NOT NULL,
    damage_inflict TEXT[] NOT NULL,
    damage_resist TEXT[] NOT NULL,
    conditions TEXT[] NOT NULL,
    saving_throw TEXT[] NOT NULL,
    attack_type TEXT,
    data JSONB NOT NULL
);
CREATE TABLE IF NOT EXISTS conditions (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);
CREATE TABLE IF NOT EXISTS bestiary (
    id INTEGER GENERATED ALWAYS AS IDENTITY
);

-- ============================================================
-- Auth / Users
-- ============================================================

-- Core local user accounts. password_hash is NULL for OAuth-only users.
CREATE TABLE IF NOT EXISTS users (
    id UUID PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
    username TEXT UNIQUE NOT NULL,
    password_hash TEXT,
    email TEXT UNIQUE,
    first_name TEXT,
    last_name TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

-- External OAuth provider connections (Discord, etc.)
CREATE TABLE IF NOT EXISTS user_connections (
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    provider TEXT NOT NULL,
    provider_user_id TEXT NOT NULL,
    provider_username TEXT,
    provider_avatar TEXT,
    PRIMARY KEY (user_id, provider),
    UNIQUE (provider, provider_user_id)
);

-- ============================================================
-- Grid maps: unbounded canvas, CSPRNG TEXT ids, auth-aware
-- ============================================================

-- public_access: 'private' | 'public_view' | 'public_edit'
--   private      – only users with explicit map_permissions can see/edit
--   public_view  – anyone with the link can view; only permissioned users can edit
--   public_edit  – anyone with the link can view AND edit
CREATE TABLE IF NOT EXISTS grid_maps (
    id TEXT PRIMARY KEY NOT NULL,
    name TEXT NOT NULL,
    public_access TEXT NOT NULL DEFAULT 'private'
        CHECK (public_access IN ('private', 'public_view', 'public_edit')),
    owner_id UUID NOT NULL REFERENCES users(id),
    colors TEXT[] NOT NULL DEFAULT ARRAY[
        '#6b7280',
        '#92400e',
        '#15803d',
        '#1d4ed8',
        '#7c3aed',
        '#dc2626',
        '#ca8a04',
        '#0f172a',
        '#f9fafb'
    ],
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

-- Per-map role assignments; owner is auto-inserted on map creation
CREATE TABLE IF NOT EXISTS map_permissions (
    map_id TEXT NOT NULL REFERENCES grid_maps(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    role TEXT NOT NULL CHECK (role IN ('owner', 'editor', 'viewer')),
    PRIMARY KEY (map_id, user_id)
);

-- Maps a user has favorited; makes them appear in the user's map list modal
-- even if they have no explicit map_permissions entry (e.g. public maps)
CREATE TABLE IF NOT EXISTS map_favorites (
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    map_id TEXT NOT NULL REFERENCES grid_maps(id) ON DELETE CASCADE,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    PRIMARY KEY (user_id, map_id)
);

-- Pending/resolved requests from users wanting viewer or editor access
CREATE TABLE IF NOT EXISTS map_access_requests (
    id UUID PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(),
    map_id TEXT NOT NULL REFERENCES grid_maps(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    requested_role TEXT NOT NULL CHECK (requested_role IN ('editor', 'viewer')),
    status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'denied')),
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    UNIQUE (map_id, user_id)
);

-- Composite primary key replaces the old UUID id column
CREATE TABLE IF NOT EXISTS grid_cells (
    map_id TEXT NOT NULL REFERENCES grid_maps(id) ON DELETE CASCADE,
    x INTEGER NOT NULL,
    y INTEGER NOT NULL,
    color TEXT NOT NULL DEFAULT '#808080',
    PRIMARY KEY (map_id, x, y)
);

CREATE TABLE IF NOT EXISTS grid_tokens (
    id TEXT PRIMARY KEY NOT NULL,
    map_id TEXT NOT NULL REFERENCES grid_maps(id) ON DELETE CASCADE,
    x INTEGER NOT NULL,
    y INTEGER NOT NULL,
    label TEXT NOT NULL,
    color TEXT NOT NULL DEFAULT '#4444FF'
);
