-- Migration 040: Inference Registry
-- Creates tables for the capability-aware inference gateway:
--   inference_endpoints, model_deployments, agent_stage_bindings
-- Adds lineage columns to agent_performance_log for v3 provenance tracking.

-- ─── Helper: auto-update updated_at on row modification ───────────────────────
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- ─── inference_endpoints ──────────────────────────────────────────────────────
-- Stores registered inference service endpoints (Ollama, vLLM, OpenAI-compat, specialist).
CREATE TABLE IF NOT EXISTS inference_endpoints (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL UNIQUE,
    protocol TEXT NOT NULL CHECK (protocol IN ('ollama_native', 'openai_chat', 'specialist_http')),
    base_url TEXT NOT NULL,
    auth_secret_ref TEXT,
    auth_scheme TEXT NOT NULL DEFAULT 'bearer',
    default_headers JSONB NOT NULL DEFAULT '{}',
    health_path TEXT,
    enabled BOOLEAN NOT NULL DEFAULT TRUE,
    revision INTEGER NOT NULL DEFAULT 1,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_inference_endpoints_protocol
    ON inference_endpoints(protocol);

-- Auto-update updated_at on inference_endpoints changes
DROP TRIGGER IF EXISTS trg_inference_endpoints_updated_at ON inference_endpoints;
CREATE TRIGGER trg_inference_endpoints_updated_at
    BEFORE UPDATE ON inference_endpoints
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ─── model_deployments ────────────────────────────────────────────────────────
-- A model served by an endpoint, with declared capabilities and limits.
CREATE TABLE IF NOT EXISTS model_deployments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    endpoint_id UUID NOT NULL REFERENCES inference_endpoints(id) ON DELETE CASCADE,
    served_model_name TEXT NOT NULL,
    display_name TEXT NOT NULL,
    capabilities JSONB NOT NULL,
    context_window INTEGER,
    max_output_tokens INTEGER,
    quantization TEXT,
    runtime_metadata JSONB NOT NULL DEFAULT '{}',
    enabled BOOLEAN NOT NULL DEFAULT TRUE,
    revision INTEGER NOT NULL DEFAULT 1,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE(endpoint_id, served_model_name)
);

CREATE INDEX IF NOT EXISTS idx_model_deployments_endpoint
    ON model_deployments(endpoint_id);

-- Auto-update updated_at on model_deployments changes
DROP TRIGGER IF EXISTS trg_model_deployments_updated_at ON model_deployments;
CREATE TRIGGER trg_model_deployments_updated_at
    BEFORE UPDATE ON model_deployments
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ─── agent_stage_bindings ─────────────────────────────────────────────────────
-- Maps an agent + pipeline stage to one or more ordered model deployments.
CREATE TABLE IF NOT EXISTS agent_stage_bindings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    agent_id UUID NOT NULL REFERENCES ai_agents(id) ON DELETE CASCADE,
    stage TEXT NOT NULL,
    model_deployment_id UUID REFERENCES model_deployments(id) ON DELETE SET NULL,
    route_order INTEGER NOT NULL DEFAULT 0,
    routing_config JSONB NOT NULL DEFAULT '{}',
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    revision INTEGER NOT NULL DEFAULT 1,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE(agent_id, stage, route_order)
);

CREATE INDEX IF NOT EXISTS idx_agent_stage_bindings_agent
    ON agent_stage_bindings(agent_id);

CREATE INDEX IF NOT EXISTS idx_agent_stage_bindings_deployment
    ON agent_stage_bindings(model_deployment_id);

-- Auto-update updated_at on agent_stage_bindings changes
DROP TRIGGER IF EXISTS trg_agent_stage_bindings_updated_at ON agent_stage_bindings;
CREATE TRIGGER trg_agent_stage_bindings_updated_at
    BEFORE UPDATE ON agent_stage_bindings
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ─── Additive lineage columns on agent_performance_log ────────────────────────
-- Tracks which endpoint/deployment/binding was used for each logged invocation.
-- NOTE: Revision increment logic is handled at the application layer:
--   each UPDATE to inference_endpoints, model_deployments, or agent_stage_bindings
--   should increment the revision column (enforced by service code, not DB trigger,
--   to allow flexible conflict resolution).

ALTER TABLE agent_performance_log
    ADD COLUMN IF NOT EXISTS endpoint_id UUID REFERENCES inference_endpoints(id) ON DELETE SET NULL;

ALTER TABLE agent_performance_log
    ADD COLUMN IF NOT EXISTS deployment_id UUID REFERENCES model_deployments(id) ON DELETE SET NULL;

ALTER TABLE agent_performance_log
    ADD COLUMN IF NOT EXISTS binding_revision INTEGER;

ALTER TABLE agent_performance_log
    ADD COLUMN IF NOT EXISTS structured_mode TEXT;

CREATE INDEX IF NOT EXISTS idx_agent_perf_endpoint
    ON agent_performance_log(endpoint_id)
    WHERE endpoint_id IS NOT NULL;

CREATE INDEX IF NOT EXISTS idx_agent_perf_deployment
    ON agent_performance_log(deployment_id)
    WHERE deployment_id IS NOT NULL;
