ALTER TABLE gateway.api_keys
    ADD COLUMN IF NOT EXISTS application_id uuid REFERENCES gateway.applications(id) ON DELETE SET NULL;

CREATE INDEX IF NOT EXISTS api_keys_application_idx
    ON gateway.api_keys (application_id, enabled)
    WHERE application_id IS NOT NULL;

CREATE TABLE IF NOT EXISTS gateway.application_runtime_credentials (
    application_id uuid NOT NULL REFERENCES gateway.applications(id) ON DELETE CASCADE,
    department_id uuid REFERENCES gateway.departments(id) ON DELETE CASCADE,
    api_key_id uuid NOT NULL UNIQUE REFERENCES gateway.api_keys(id) ON DELETE CASCADE,
    encrypted_key bytea NOT NULL,
    key_kek_version integer NOT NULL,
    created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    updated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    UNIQUE NULLS NOT DISTINCT (application_id, department_id)
);

CREATE TABLE IF NOT EXISTS gateway.portal_conversations (
    id uuid PRIMARY KEY,
    portal_user_id uuid NOT NULL REFERENCES gateway.portal_users(id) ON DELETE CASCADE,
    application_id uuid NOT NULL REFERENCES gateway.applications(id) ON DELETE CASCADE,
    title text NOT NULL DEFAULT '新会话' CHECK (length(title) BETWEEN 1 AND 160),
    status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','archived')),
    busy boolean NOT NULL DEFAULT false,
    busy_token uuid,
    busy_since timestamptz,
    next_sequence integer NOT NULL DEFAULT 1 CHECK (next_sequence BETWEEN 1 AND 202),
    created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    updated_at timestamptz NOT NULL DEFAULT clock_timestamp()
);

CREATE INDEX IF NOT EXISTS portal_conversations_user_time_idx
    ON gateway.portal_conversations (portal_user_id, updated_at DESC);

CREATE TABLE IF NOT EXISTS gateway.portal_conversation_messages (
    id uuid PRIMARY KEY,
    conversation_id uuid NOT NULL REFERENCES gateway.portal_conversations(id) ON DELETE CASCADE,
    sequence integer NOT NULL CHECK (sequence BETWEEN 1 AND 200),
    role text NOT NULL CHECK (role IN ('user','assistant')),
    content text NOT NULL CHECK (length(content) BETWEEN 1 AND 100000),
    previous_hash char(64) NOT NULL,
    message_hash char(64) NOT NULL,
    created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
    UNIQUE (conversation_id, sequence)
);

COMMENT ON TABLE gateway.portal_conversation_messages IS
    'Server-managed immutable conversation history. A SHA-256 hash chain detects database-side sequence/content corruption before replay.';
