-- Migration: Access Management Schema
-- Description: Adds RPC product subscriptions, richer API key metadata, and usage logging.

ALTER TABLE api_keys
    ADD COLUMN IF NOT EXISTS product_slug VARCHAR(100),
    ADD COLUMN IF NOT EXISTS scopes TEXT[] DEFAULT ARRAY[]::TEXT[],
    ADD COLUMN IF NOT EXISTS monthly_quota INTEGER,
    ADD COLUMN IF NOT EXISTS requests_used INTEGER NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS approved BOOLEAN NOT NULL DEFAULT false,
    ADD COLUMN IF NOT EXISTS approved_at TIMESTAMP,
    ADD COLUMN IF NOT EXISTS approved_by VARCHAR(255),
    ADD COLUMN IF NOT EXISTS last_ip_address INET;

CREATE TABLE IF NOT EXISTS rpc_products (
    slug VARCHAR(100) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    provider VARCHAR(100) NOT NULL,
    vmid INTEGER NOT NULL,
    http_url TEXT NOT NULL,
    ws_url TEXT,
    default_tier VARCHAR(20) NOT NULL,
    requires_approval BOOLEAN NOT NULL DEFAULT false,
    billing_model VARCHAR(50) NOT NULL DEFAULT 'subscription',
    description TEXT,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS user_product_subscriptions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    product_slug VARCHAR(100) NOT NULL REFERENCES rpc_products(slug) ON DELETE CASCADE,
    tier VARCHAR(20) NOT NULL CHECK (tier IN ('free', 'pro', 'enterprise')),
    status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'suspended', 'revoked')),
    monthly_quota INTEGER,
    requests_used INTEGER NOT NULL DEFAULT 0,
    requires_approval BOOLEAN NOT NULL DEFAULT false,
    approved_at TIMESTAMP,
    approved_by VARCHAR(255),
    notes TEXT,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(user_id, product_slug)
);

CREATE TABLE IF NOT EXISTS api_key_usage_logs (
    id BIGSERIAL PRIMARY KEY,
    api_key_id UUID NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE,
    product_slug VARCHAR(100),
    method_name VARCHAR(100),
    request_count INTEGER NOT NULL DEFAULT 1,
    window_start TIMESTAMP NOT NULL DEFAULT NOW(),
    window_end TIMESTAMP,
    last_ip_address INET,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_user_product_subscriptions_user ON user_product_subscriptions(user_id);
CREATE INDEX IF NOT EXISTS idx_user_product_subscriptions_product ON user_product_subscriptions(product_slug);
CREATE INDEX IF NOT EXISTS idx_user_product_subscriptions_status ON user_product_subscriptions(status);
CREATE INDEX IF NOT EXISTS idx_api_key_usage_logs_key ON api_key_usage_logs(api_key_id);
CREATE INDEX IF NOT EXISTS idx_api_key_usage_logs_product ON api_key_usage_logs(product_slug);

INSERT INTO rpc_products (slug, name, provider, vmid, http_url, ws_url, default_tier, requires_approval, billing_model, description)
VALUES
    ('core-rpc', 'Core RPC', 'besu-core', 2101, 'https://rpc-http-prv.d-bis.org', 'wss://rpc-ws-prv.d-bis.org', 'enterprise', true, 'contract', 'Private Chain 138 Core RPC for operator-grade administration and sensitive workloads.'),
    ('alltra-rpc', 'Alltra RPC', 'alltra', 2102, 'http://192.168.11.212:8545', 'ws://192.168.11.212:8546', 'pro', false, 'subscription', 'Dedicated Alltra RPC lane for partner traffic, subscription access, and API-key-gated usage.'),
    ('thirdweb-rpc', 'Thirdweb RPC', 'thirdweb', 2103, 'http://192.168.11.217:8545', 'ws://192.168.11.217:8546', 'pro', false, 'subscription', 'Thirdweb-oriented Chain 138 RPC lane suitable for managed SaaS access and API-token paywalling.')
ON CONFLICT (slug) DO UPDATE SET
    name = EXCLUDED.name,
    provider = EXCLUDED.provider,
    vmid = EXCLUDED.vmid,
    http_url = EXCLUDED.http_url,
    ws_url = EXCLUDED.ws_url,
    default_tier = EXCLUDED.default_tier,
    requires_approval = EXCLUDED.requires_approval,
    billing_model = EXCLUDED.billing_model,
    description = EXCLUDED.description,
    updated_at = NOW();
