-- Migration 000001: Initial schema
-- Tables: tenants, users, api_keys
-- Row Level Security enabled for logical multi-tenancy (physical isolation in V2)

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- ============================================================
-- TENANTS
-- ============================================================
CREATE TABLE tenants (
    id         UUID        PRIMARY KEY DEFAULT uuid_generate_v4(),
    name       TEXT        NOT NULL,
    slug       TEXT        NOT NULL UNIQUE,          -- URL-safe identifier, e.g. "acme-corp"
    plan       TEXT        NOT NULL DEFAULT 'starter' CHECK (plan IN ('starter', 'business', 'enterprise')),
    is_active  BOOLEAN     NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_tenants_slug ON tenants(slug);

-- ============================================================
-- USERS
-- ============================================================
CREATE TABLE users (
    id          UUID        PRIMARY KEY DEFAULT uuid_generate_v4(),
    tenant_id   UUID        NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
    external_id TEXT        NOT NULL,                -- Keycloak subject (sub claim)
    email       TEXT        NOT NULL,
    role        TEXT        NOT NULL DEFAULT 'user'  CHECK (role IN ('admin', 'manager', 'user', 'auditor')),
    department  TEXT,                                -- e.g. "finance", "legal", "engineering"
    is_active   BOOLEAN     NOT NULL DEFAULT TRUE,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (tenant_id, external_id),
    UNIQUE (tenant_id, email)
);

CREATE INDEX idx_users_tenant_id   ON users(tenant_id);
CREATE INDEX idx_users_external_id ON users(external_id);
CREATE INDEX idx_users_email       ON users(tenant_id, email);

-- ============================================================
-- API KEYS
-- Keys are stored as SHA-256 hashes — never in plaintext.
-- The first 8 chars are kept as prefix for identification (e.g. "sk-vyl_ab12cd34...").
-- ============================================================
CREATE TABLE api_keys (
    id           UUID        PRIMARY KEY DEFAULT uuid_generate_v4(),
    tenant_id    UUID        NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
    name         TEXT        NOT NULL,               -- Human-readable label, e.g. "Finance dept key"
    key_hash     TEXT        NOT NULL UNIQUE,        -- SHA-256(raw_key), hex-encoded
    key_prefix   TEXT        NOT NULL,               -- First 8 chars of raw key for display
    provider     TEXT        NOT NULL CHECK (provider IN ('openai', 'anthropic', 'azure', 'mistral', 'ollama')),
    scopes       TEXT[]      NOT NULL DEFAULT '{}',  -- e.g. {'chat:completions', 'embeddings'}
    is_active    BOOLEAN     NOT NULL DEFAULT TRUE,
    expires_at   TIMESTAMPTZ,                        -- NULL = no expiry
    last_used_at TIMESTAMPTZ,
    created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_api_keys_tenant_id ON api_keys(tenant_id);
CREATE INDEX idx_api_keys_key_hash  ON api_keys(key_hash);

-- ============================================================
-- ROW LEVEL SECURITY
-- App connects as role 'veylant_app' and sets app.tenant_id per session.
-- Policies are added here for completeness; the role is created in env setup.
-- ============================================================
ALTER TABLE tenants  ENABLE ROW LEVEL SECURITY;
ALTER TABLE users    ENABLE ROW LEVEL SECURITY;
ALTER TABLE api_keys ENABLE ROW LEVEL SECURITY;

-- Superuser bypasses RLS — dev connections use superuser, prod connections use veylant_app role.
-- Policies below apply only to veylant_app role (added in env-specific setup scripts).

-- ============================================================
-- updated_at auto-update trigger
-- ============================================================
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tenants_updated_at  BEFORE UPDATE ON tenants  FOR EACH ROW EXECUTE FUNCTION set_updated_at();
CREATE TRIGGER users_updated_at    BEFORE UPDATE ON users    FOR EACH ROW EXECUTE FUNCTION set_updated_at();
CREATE TRIGGER api_keys_updated_at BEFORE UPDATE ON api_keys FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ============================================================
-- Seed: default development tenant and admin user
-- (Development only — replaced by real onboarding in prod)
-- ============================================================
INSERT INTO tenants (id, name, slug, plan) VALUES
    ('00000000-0000-0000-0000-000000000001', 'Veylant Dev', 'veylant-dev', 'enterprise');

INSERT INTO users (tenant_id, external_id, email, role, department) VALUES
    ('00000000-0000-0000-0000-000000000001', 'dev-admin', 'admin@veylant.dev', 'admin', 'engineering');
