-- ============================================================================
-- SCHEMA: vip
-- TABLES: tiers, subscriptions, model_access
-- DESCRIPTION: Sistema VIP con tiers y modelos exclusivos
-- VERSION: 1.0.0
-- CREATED: 2026-01-10
-- ============================================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS vip;

-- Enums
DO $$ BEGIN
    CREATE TYPE vip.tier_type AS ENUM (
        'GOLD',         -- Tier Gold - $199/mes
        'PLATINUM',     -- Tier Platinum - $399/mes
        'DIAMOND'       -- Tier Diamond - $999/mes
    );
EXCEPTION WHEN duplicate_object THEN null; END $$;

DO $$ BEGIN
    CREATE TYPE vip.subscription_status AS ENUM (
        'trialing',     -- En periodo de prueba
        'active',       -- Activa y pagando
        'past_due',     -- Pago atrasado
        'cancelled',    -- Cancelada
        'expired'       -- Expirada
    );
EXCEPTION WHEN duplicate_object THEN null; END $$;

-- Tabla de definicion de Tiers
CREATE TABLE IF NOT EXISTS vip.tiers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Identificacion
    tier vip.tier_type UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    tagline VARCHAR(200),

    -- Precios
    price_monthly DECIMAL(10, 2) NOT NULL,
    price_yearly DECIMAL(10, 2),
    currency VARCHAR(3) DEFAULT 'USD',

    -- Stripe
    stripe_product_id VARCHAR(255),
    stripe_price_monthly_id VARCHAR(255),
    stripe_price_yearly_id VARCHAR(255),

    -- Beneficios (JSONB array)
    benefits JSONB NOT NULL DEFAULT '[]',
    -- Ejemplo:
    -- [
    --   {"name": "Modelo Ensemble Pro", "included": true},
    --   {"name": "Predicciones VIP", "value": "50/mes"},
    --   {"name": "Soporte prioritario", "included": true}
    -- ]

    -- Limites
    limits JSONB NOT NULL DEFAULT '{}',
    -- Ejemplo:
    -- {
    --   "vip_predictions_per_month": 50,
    --   "api_calls_per_minute": 30,
    --   "exclusive_models": ["ensemble_pro"]
    -- }

    -- Modelos exclusivos incluidos
    included_models VARCHAR[] DEFAULT '{}',

    -- Display
    color VARCHAR(7),
    icon VARCHAR(50),
    sort_order INT DEFAULT 0,
    is_popular BOOLEAN DEFAULT FALSE,

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE vip.tiers IS
'Definicion de los tiers VIP disponibles (Gold, Platinum, Diamond)';

-- Tabla de suscripciones VIP
CREATE TABLE IF NOT EXISTS vip.subscriptions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    user_id UUID NOT NULL,
    tier_id UUID NOT NULL REFERENCES vip.tiers(id),

    -- Stripe
    stripe_subscription_id VARCHAR(255) UNIQUE,
    stripe_customer_id VARCHAR(255),

    -- Estado
    status vip.subscription_status NOT NULL DEFAULT 'trialing',

    -- Periodo
    interval VARCHAR(10) DEFAULT 'month',
    current_period_start TIMESTAMPTZ,
    current_period_end TIMESTAMPTZ,

    -- Trial
    trial_start TIMESTAMPTZ,
    trial_end TIMESTAMPTZ,

    -- Cancelacion
    cancel_at TIMESTAMPTZ,
    cancelled_at TIMESTAMPTZ,
    cancel_reason VARCHAR(500),

    -- Uso del periodo actual
    vip_predictions_used INT DEFAULT 0,
    api_calls_this_period INT DEFAULT 0,
    last_usage_reset TIMESTAMPTZ DEFAULT NOW(),

    -- Metadata
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),

    -- Solo una suscripcion activa por usuario
    CONSTRAINT unique_active_vip_subscription
        UNIQUE (tenant_id, user_id)
);

COMMENT ON TABLE vip.subscriptions IS
'Suscripciones VIP activas de usuarios';

-- Tabla de acceso a modelos exclusivos
CREATE TABLE IF NOT EXISTS vip.model_access (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    subscription_id UUID NOT NULL REFERENCES vip.subscriptions(id) ON DELETE CASCADE,

    -- Modelo
    model_id VARCHAR(100) NOT NULL,
    model_name VARCHAR(200),

    -- Uso
    predictions_generated INT DEFAULT 0,
    last_used_at TIMESTAMPTZ,

    -- Limites especificos del modelo
    daily_limit INT,
    monthly_limit INT,
    daily_used INT DEFAULT 0,
    monthly_used INT DEFAULT 0,

    -- Acceso
    granted_at TIMESTAMPTZ DEFAULT NOW(),
    expires_at TIMESTAMPTZ,

    UNIQUE(subscription_id, model_id)
);

COMMENT ON TABLE vip.model_access IS
'Registro de acceso a modelos exclusivos por suscripcion VIP';

-- Indices
CREATE INDEX IF NOT EXISTS idx_vip_tiers_active
    ON vip.tiers(is_active) WHERE is_active = TRUE;

CREATE INDEX IF NOT EXISTS idx_vip_subs_tenant
    ON vip.subscriptions(tenant_id);

CREATE INDEX IF NOT EXISTS idx_vip_subs_user
    ON vip.subscriptions(user_id);

CREATE INDEX IF NOT EXISTS idx_vip_subs_status
    ON vip.subscriptions(status);

CREATE INDEX IF NOT EXISTS idx_vip_subs_stripe
    ON vip.subscriptions(stripe_subscription_id);

CREATE INDEX IF NOT EXISTS idx_vip_access_sub
    ON vip.model_access(subscription_id);

CREATE INDEX IF NOT EXISTS idx_vip_access_model
    ON vip.model_access(model_id);

-- Trigger updated_at
CREATE OR REPLACE FUNCTION vip.update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS vip_tiers_updated ON vip.tiers;
CREATE TRIGGER vip_tiers_updated
    BEFORE UPDATE ON vip.tiers
    FOR EACH ROW
    EXECUTE FUNCTION vip.update_timestamp();

DROP TRIGGER IF EXISTS vip_subs_updated ON vip.subscriptions;
CREATE TRIGGER vip_subs_updated
    BEFORE UPDATE ON vip.subscriptions
    FOR EACH ROW
    EXECUTE FUNCTION vip.update_timestamp();

-- Funcion para verificar acceso VIP
CREATE OR REPLACE FUNCTION vip.check_vip_access(
    p_user_id UUID,
    p_model_id VARCHAR(100)
)
RETURNS BOOLEAN AS $$
DECLARE
    v_has_access BOOLEAN;
BEGIN
    SELECT EXISTS (
        SELECT 1
        FROM vip.subscriptions s
        JOIN vip.model_access ma ON ma.subscription_id = s.id
        WHERE s.user_id = p_user_id
          AND s.status = 'active'
          AND ma.model_id = p_model_id
          AND (ma.expires_at IS NULL OR ma.expires_at > NOW())
    ) INTO v_has_access;

    RETURN v_has_access;
END;
$$ LANGUAGE plpgsql;

-- RLS
ALTER TABLE vip.tiers ENABLE ROW LEVEL SECURITY;
ALTER TABLE vip.subscriptions ENABLE ROW LEVEL SECURITY;
ALTER TABLE vip.model_access ENABLE ROW LEVEL SECURITY;

CREATE POLICY tiers_read_all ON vip.tiers
    FOR SELECT USING (TRUE);

CREATE POLICY subs_tenant_isolation ON vip.subscriptions
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

CREATE POLICY access_via_subscription ON vip.model_access
    FOR ALL
    USING (
        subscription_id IN (
            SELECT id FROM vip.subscriptions
            WHERE tenant_id = current_setting('app.current_tenant_id', true)::UUID
        )
    );

-- Grants
GRANT SELECT ON vip.tiers TO trading_app;
GRANT SELECT, INSERT, UPDATE ON vip.subscriptions TO trading_app;
GRANT SELECT, INSERT, UPDATE ON vip.model_access TO trading_app;
GRANT SELECT ON vip.tiers TO trading_readonly;
GRANT SELECT ON vip.subscriptions TO trading_readonly;
