-- Fractafrag Database Bootstrap
-- Runs on first container start via docker-entrypoint-initdb.d

-- Enable required extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "vector";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";  -- for text search

-- ════════════════════════════════════════════════════════════
-- USERS
-- ════════════════════════════════════════════════════════════
CREATE TABLE users (
    id                      UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username                TEXT UNIQUE NOT NULL,
    email                   TEXT UNIQUE NOT NULL,
    password_hash           TEXT NOT NULL,
    role                    TEXT NOT NULL DEFAULT 'user',        -- user, moderator, admin
    trust_tier              TEXT NOT NULL DEFAULT 'standard',    -- standard, creator, trusted_api
    is_system               BOOLEAN NOT NULL DEFAULT FALSE,      -- platform system account (fractafrag)
    stripe_customer_id      TEXT,
    subscription_tier       TEXT DEFAULT 'free',                 -- free, pro, studio
    ai_credits_remaining    INTEGER DEFAULT 0,
    taste_vector            vector(512),                         -- pgvector: learned taste embedding
    -- Creator economy stubs (Section 11f — deferred, schema only)
    is_verified_creator     BOOLEAN DEFAULT FALSE,
    verified_creator_at     TIMESTAMPTZ,
    stripe_connect_account_id TEXT,
    -- Timestamps
    created_at              TIMESTAMPTZ DEFAULT NOW(),
    last_active_at          TIMESTAMPTZ
);

-- ════════════════════════════════════════════════════════════
-- SHADERS
-- ════════════════════════════════════════════════════════════
CREATE TABLE shaders (
    id                  UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    author_id           UUID REFERENCES users(id) ON DELETE SET NULL,
    title               TEXT NOT NULL,
    description         TEXT,
    glsl_code           TEXT NOT NULL,
    status              TEXT NOT NULL DEFAULT 'published',  -- draft, published, archived
    is_public           BOOLEAN DEFAULT TRUE,
    is_ai_generated     BOOLEAN DEFAULT FALSE,
    is_system           BOOLEAN DEFAULT FALSE,              -- generated by fractafrag platform
    ai_provider         TEXT,                               -- anthropic, openai, ollama, null
    system_label        TEXT,                               -- e.g. 'fractafrag-curated', 'fractafrag-generated'
    thumbnail_url       TEXT,
    preview_url         TEXT,
    render_status       TEXT DEFAULT 'pending',             -- pending, rendering, ready, failed
    style_vector        vector(512),                        -- pgvector: visual style embedding
    style_metadata      JSONB,                              -- { chaos_level, color_temp, motion_type, ... }
    tags                TEXT[],
    shader_type         TEXT DEFAULT '2d',                  -- 2d, 3d, audio-reactive
    forked_from         UUID REFERENCES shaders(id) ON DELETE SET NULL,
    current_version     INTEGER NOT NULL DEFAULT 1,         -- current version number
    view_count          INTEGER DEFAULT 0,
    score               FLOAT DEFAULT 0,                    -- cached hot score for feed ranking
    -- Creator economy stubs (Section 11f)
    access_tier                     TEXT DEFAULT 'open',
    source_unlock_price_cents       INTEGER,
    commercial_license_price_cents  INTEGER,
    verified_creator_shader         BOOLEAN DEFAULT FALSE,
    -- Timestamps
    created_at          TIMESTAMPTZ DEFAULT NOW(),
    updated_at          TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- SHADER VERSIONS — immutable snapshots of each edit
-- ════════════════════════════════════════════════════════════
CREATE TABLE shader_versions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    shader_id       UUID NOT NULL REFERENCES shaders(id) ON DELETE CASCADE,
    version_number  INTEGER NOT NULL,
    glsl_code       TEXT NOT NULL,
    title           TEXT NOT NULL,
    description     TEXT,
    tags            TEXT[],
    style_metadata  JSONB,
    change_note     TEXT,               -- optional: "fixed the color bleeding", "added mouse interaction"
    thumbnail_url   TEXT,
    created_at      TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE (shader_id, version_number)
);

-- ════════════════════════════════════════════════════════════
-- VOTES
-- ════════════════════════════════════════════════════════════
CREATE TABLE votes (
    id         UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id    UUID REFERENCES users(id) ON DELETE CASCADE,
    shader_id  UUID REFERENCES shaders(id) ON DELETE CASCADE,
    value      SMALLINT NOT NULL CHECK (value IN (-1, 1)),
    created_at TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE (user_id, shader_id)
);

-- ════════════════════════════════════════════════════════════
-- ENGAGEMENT EVENTS (dwell time, replays, shares)
-- ════════════════════════════════════════════════════════════
CREATE TABLE engagement_events (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id     UUID REFERENCES users(id) ON DELETE SET NULL,
    session_id  TEXT,
    shader_id   UUID REFERENCES shaders(id) ON DELETE CASCADE,
    event_type  TEXT NOT NULL,
    dwell_secs  FLOAT,
    metadata    JSONB,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- DESIRES / BOUNTIES
-- ════════════════════════════════════════════════════════════
CREATE TABLE desires (
    id               UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    author_id        UUID REFERENCES users(id) ON DELETE SET NULL,
    prompt_text      TEXT NOT NULL,
    prompt_embedding vector(512),
    style_hints      JSONB,
    tip_amount_cents INTEGER DEFAULT 0,
    status           TEXT DEFAULT 'open',
    heat_score       FLOAT DEFAULT 1,
    fulfilled_by_shader UUID REFERENCES shaders(id) ON DELETE SET NULL,
    fulfilled_at     TIMESTAMPTZ,
    expires_at       TIMESTAMPTZ,
    created_at       TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE desire_clusters (
    cluster_id  UUID,
    desire_id   UUID REFERENCES desires(id) ON DELETE CASCADE,
    similarity  FLOAT,
    PRIMARY KEY (cluster_id, desire_id)
);

-- ════════════════════════════════════════════════════════════
-- BOUNTY TIPS
-- ════════════════════════════════════════════════════════════
CREATE TABLE bounty_tips (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    desire_id       UUID REFERENCES desires(id) ON DELETE CASCADE,
    tipper_id       UUID REFERENCES users(id) ON DELETE SET NULL,
    amount_cents    INTEGER NOT NULL,
    stripe_payment_intent_id TEXT,
    status          TEXT DEFAULT 'held',
    created_at      TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- CREATOR PAYOUTS
-- ════════════════════════════════════════════════════════════
CREATE TABLE creator_payouts (
    id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    creator_id        UUID REFERENCES users(id) ON DELETE SET NULL,
    desire_id         UUID REFERENCES desires(id) ON DELETE SET NULL,
    gross_amount_cents  INTEGER,
    platform_fee_cents  INTEGER,
    net_amount_cents    INTEGER,
    stripe_transfer_id  TEXT,
    status              TEXT DEFAULT 'pending',
    created_at          TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- API KEYS (for MCP clients)
-- ════════════════════════════════════════════════════════════
CREATE TABLE api_keys (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id     UUID REFERENCES users(id) ON DELETE CASCADE,
    key_hash    TEXT UNIQUE NOT NULL,
    key_prefix  TEXT NOT NULL,
    name        TEXT,
    trust_tier  TEXT DEFAULT 'probation',
    submissions_approved INTEGER DEFAULT 0,
    rate_limit_per_hour  INTEGER DEFAULT 10,
    last_used_at TIMESTAMPTZ,
    created_at  TIMESTAMPTZ DEFAULT NOW(),
    revoked_at  TIMESTAMPTZ
);

-- ════════════════════════════════════════════════════════════
-- AI GENERATION LOG
-- ════════════════════════════════════════════════════════════
CREATE TABLE generation_log (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id     UUID REFERENCES users(id) ON DELETE SET NULL,
    shader_id   UUID REFERENCES shaders(id) ON DELETE SET NULL,
    provider    TEXT NOT NULL,
    prompt_text TEXT,
    tokens_used INTEGER,
    cost_cents  INTEGER,
    success     BOOLEAN,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- COMMENTS (schema in place, feature deferred to post-M5)
-- ════════════════════════════════════════════════════════════
CREATE TABLE comments (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    shader_id   UUID REFERENCES shaders(id) ON DELETE CASCADE,
    author_id   UUID REFERENCES users(id) ON DELETE SET NULL,
    body        TEXT NOT NULL,
    parent_id   UUID REFERENCES comments(id) ON DELETE CASCADE,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- CREATOR ECONOMY STUBS (Section 11f — dormant until activated)
-- ════════════════════════════════════════════════════════════
CREATE TABLE source_unlocks (
    id                          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    shader_id                   UUID REFERENCES shaders(id) ON DELETE CASCADE,
    buyer_id                    UUID REFERENCES users(id) ON DELETE SET NULL,
    license_type                TEXT NOT NULL,
    amount_cents                INTEGER NOT NULL,
    platform_fee_cents          INTEGER NOT NULL,
    stripe_payment_intent_id    TEXT,
    created_at                  TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE creator_engagement_snapshots (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    creator_id      UUID REFERENCES users(id) ON DELETE CASCADE,
    month           DATE NOT NULL,
    total_score     FLOAT NOT NULL,
    pool_share      FLOAT,
    payout_cents    INTEGER,
    paid_at         TIMESTAMPTZ,
    created_at      TIMESTAMPTZ DEFAULT NOW()
);

-- ════════════════════════════════════════════════════════════
-- INDEXES
-- ════════════════════════════════════════════════════════════

-- Feed performance
CREATE INDEX idx_shaders_score ON shaders(score DESC) WHERE is_public = TRUE AND status = 'published';
CREATE INDEX idx_shaders_created ON shaders(created_at DESC) WHERE is_public = TRUE AND status = 'published';
CREATE INDEX idx_shaders_tags ON shaders USING GIN(tags);
CREATE INDEX idx_shaders_render_status ON shaders(render_status) WHERE render_status != 'ready';
CREATE INDEX idx_shaders_status ON shaders(status);
CREATE INDEX idx_shaders_author_status ON shaders(author_id, status, updated_at DESC);
CREATE INDEX idx_shaders_system ON shaders(is_system) WHERE is_system = TRUE;

-- Versioning
CREATE INDEX idx_shader_versions_shader ON shader_versions(shader_id, version_number DESC);

-- Recommendation (pgvector HNSW — works on empty tables)
CREATE INDEX idx_shaders_style_vector ON shaders
    USING hnsw (style_vector vector_cosine_ops) WITH (m = 16, ef_construction = 64);
CREATE INDEX idx_users_taste_vector ON users
    USING hnsw (taste_vector vector_cosine_ops) WITH (m = 16, ef_construction = 64);
CREATE INDEX idx_desires_embedding ON desires
    USING hnsw (prompt_embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

-- Engagement
CREATE INDEX idx_engagement_user ON engagement_events(user_id, created_at DESC);
CREATE INDEX idx_engagement_shader ON engagement_events(shader_id, event_type);
CREATE INDEX idx_engagement_session ON engagement_events(session_id, created_at DESC)
    WHERE session_id IS NOT NULL;

-- Desires / bounties
CREATE INDEX idx_desires_status ON desires(status, heat_score DESC);
CREATE INDEX idx_desires_author ON desires(author_id);

-- API keys
CREATE INDEX idx_api_keys_user ON api_keys(user_id) WHERE revoked_at IS NULL;
CREATE INDEX idx_api_keys_prefix ON api_keys(key_prefix);

-- Votes
CREATE INDEX idx_votes_shader ON votes(shader_id);
CREATE INDEX idx_votes_user ON votes(user_id);

-- Comments
CREATE INDEX idx_comments_shader ON comments(shader_id, created_at);
CREATE INDEX idx_comments_parent ON comments(parent_id);

-- Text search
CREATE INDEX idx_shaders_title_trgm ON shaders USING GIN(title gin_trgm_ops);
CREATE INDEX idx_desires_prompt_trgm ON desires USING GIN(prompt_text gin_trgm_ops);

-- ════════════════════════════════════════════════════════════
-- SYSTEM ACCOUNT: The "fractafrag" platform user
-- All system-generated/curated shaders are authored by this account
-- ════════════════════════════════════════════════════════════
INSERT INTO users (id, username, email, password_hash, role, trust_tier, is_system, subscription_tier, is_verified_creator)
VALUES (
    '00000000-0000-0000-0000-000000000001',
    'fractafrag',
    'system@fractafrag.local',
    '$2b$12$000000000000000000000000000000000000000000000000000000', -- not a valid login
    'admin',
    'trusted_api',
    TRUE,
    'studio',
    TRUE
);
