CREATE SCHEMA IF NOT EXISTS gateway;

CREATE TABLE IF NOT EXISTS gateway.outbox_events (
    event_id uuid PRIMARY KEY,
    event_type text NOT NULL,
    event_version integer NOT NULL CHECK (event_version > 0),
    tenant_id uuid,
    aggregate_type text NOT NULL,
    aggregate_id text NOT NULL,
    payload jsonb NOT NULL,
    trace_context jsonb NOT NULL DEFAULT '{}'::jsonb,
    occurred_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    available_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    attempts integer NOT NULL DEFAULT 0 CHECK (attempts >= 0),
    locked_at timestamptz,
    locked_by text,
    processed_at timestamptz,
    last_error text
);

CREATE INDEX IF NOT EXISTS outbox_events_pending_idx
    ON gateway.outbox_events (available_at, occurred_at)
    WHERE processed_at IS NULL;

CREATE TABLE IF NOT EXISTS gateway.event_consumptions (
    subscriber text NOT NULL,
    event_id uuid NOT NULL,
    consumed_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    PRIMARY KEY (subscriber, event_id)
);

CREATE TABLE IF NOT EXISTS gateway.api_keys (
    id uuid PRIMARY KEY,
    tenant_id uuid,
    name text NOT NULL,
    key_prefix varchar(16) NOT NULL,
    key_hash bytea NOT NULL,
    scopes text[] NOT NULL DEFAULT '{}',
    enabled boolean NOT NULL DEFAULT true,
    expires_at timestamptz,
    last_used_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    updated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    UNIQUE (key_prefix, key_hash)
);

CREATE INDEX IF NOT EXISTS api_keys_tenant_idx ON gateway.api_keys (tenant_id, enabled);

CREATE TABLE IF NOT EXISTS gateway.providers (
    id uuid PRIMARY KEY,
    tenant_id uuid,
    code text NOT NULL,
    adapter text NOT NULL,
    base_url text NOT NULL,
    encrypted_credentials bytea NOT NULL,
    credential_kek_version integer NOT NULL,
    capabilities text[] NOT NULL DEFAULT '{}',
    config jsonb NOT NULL DEFAULT '{}'::jsonb,
    enabled boolean NOT NULL DEFAULT true,
    revision bigint NOT NULL DEFAULT 1,
    created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    updated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    UNIQUE NULLS NOT DISTINCT (tenant_id, code)
);

CREATE TABLE IF NOT EXISTS gateway.audit_events (
    id uuid NOT NULL,
    tenant_id uuid,
    request_id text NOT NULL,
    actor_id uuid,
    api_key_id uuid,
    provider_code text,
    model text,
    protocol text NOT NULL,
    status_code integer,
    prompt_tokens bigint CHECK (prompt_tokens IS NULL OR prompt_tokens >= 0),
    completion_tokens bigint CHECK (completion_tokens IS NULL OR completion_tokens >= 0),
    cost_microunits bigint CHECK (cost_microunits IS NULL OR cost_microunits >= 0),
    latency_ms integer CHECK (latency_ms IS NULL OR latency_ms >= 0),
    request_preview text CHECK (request_preview IS NULL OR octet_length(request_preview) <= 65536),
    response_preview text CHECK (response_preview IS NULL OR octet_length(response_preview) <= 65536),
    labels jsonb NOT NULL DEFAULT '{}'::jsonb,
    recorded_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    PRIMARY KEY (id, recorded_at)
) PARTITION BY RANGE (recorded_at);

CREATE TABLE IF NOT EXISTS gateway.audit_events_default
    PARTITION OF gateway.audit_events DEFAULT;

CREATE INDEX IF NOT EXISTS audit_events_default_tenant_time_idx
    ON gateway.audit_events_default (tenant_id, recorded_at DESC);
CREATE INDEX IF NOT EXISTS audit_events_default_request_idx
    ON gateway.audit_events_default (request_id);

COMMENT ON TABLE gateway.audit_events IS
    'PostgreSQL baseline audit storage. Full unbounded bodies are deliberately not retained.';

