-- ============ LLM Endpoints ============
CREATE TABLE llm_endpoints (
    id                 UUID PRIMARY KEY,
    provider           TEXT NOT NULL CHECK (provider IN ('anthropic','openai','gemini')),
    display_name       TEXT NOT NULL,
    base_url           TEXT NOT NULL,
    api_key_encrypted  BYTEA NOT NULL,
    created_by         UUID NOT NULL REFERENCES users(id),
    created_at         TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at         TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX llm_endpoints_provider_idx ON llm_endpoints(provider);

-- ============ LLM Models ============
CREATE TABLE llm_models (
    id                                UUID PRIMARY KEY,
    endpoint_id                       UUID NOT NULL REFERENCES llm_endpoints(id) ON DELETE RESTRICT,
    model_id                          TEXT NOT NULL,
    display_name                      TEXT NOT NULL,
    capabilities                      JSONB NOT NULL DEFAULT '{}'::jsonb,
    context_window                    INT NOT NULL,
    max_output_tokens                 INT NOT NULL,
    prompt_price_per_million_usd      NUMERIC(10,6) NOT NULL DEFAULT 0,
    completion_price_per_million_usd  NUMERIC(10,6) NOT NULL DEFAULT 0,
    thinking_price_per_million_usd    NUMERIC(10,6) NOT NULL DEFAULT 0,
    is_title_generator                BOOLEAN NOT NULL DEFAULT false,
    enabled                           BOOLEAN NOT NULL DEFAULT true,
    sort_order                        INT NOT NULL DEFAULT 0,
    created_at                        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at                        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (endpoint_id, model_id)
);
CREATE UNIQUE INDEX llm_models_one_title_generator
    ON llm_models ((1)) WHERE is_title_generator;
CREATE INDEX llm_models_enabled_sort_idx ON llm_models(enabled, sort_order);

-- ============ Prompt Templates ============
CREATE TABLE prompt_templates (
    id          UUID PRIMARY KEY,
    name        TEXT NOT NULL,
    content     TEXT NOT NULL,
    scope       TEXT NOT NULL CHECK (scope IN ('system','user')),
    owner_id    UUID REFERENCES users(id),
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CHECK ((scope='user' AND owner_id IS NOT NULL) OR (scope='system' AND owner_id IS NULL))
);
CREATE INDEX prompt_templates_scope_owner_idx ON prompt_templates(scope, owner_id);

-- ============ Conversations ============
CREATE TABLE conversations (
    id                    UUID PRIMARY KEY,
    user_id               UUID NOT NULL REFERENCES users(id),
    project_id            UUID REFERENCES projects(id),
    workspace_id          UUID REFERENCES workspaces(id),
    issue_id              UUID REFERENCES issues(id),
    model_id              UUID NOT NULL REFERENCES llm_models(id) ON DELETE RESTRICT,
    system_prompt         TEXT NOT NULL DEFAULT '',
    title                 TEXT,
    title_generated_at    TIMESTAMPTZ,
    created_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at            TIMESTAMPTZ
);
CREATE INDEX conversations_user_list_idx ON conversations(user_id, deleted_at, updated_at DESC);
CREATE INDEX conversations_project_idx   ON conversations(project_id) WHERE project_id IS NOT NULL;
CREATE INDEX conversations_workspace_idx ON conversations(workspace_id) WHERE workspace_id IS NOT NULL;
CREATE INDEX conversations_issue_idx     ON conversations(issue_id) WHERE issue_id IS NOT NULL;

-- ============ Messages ============
CREATE TABLE messages (
    id                  BIGSERIAL PRIMARY KEY,
    conversation_id     UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
    role                TEXT NOT NULL CHECK (role IN ('user','assistant')),
    content             TEXT NOT NULL DEFAULT '',
    thinking            TEXT,
    tool_calls          JSONB,
    status              TEXT NOT NULL CHECK (status IN ('pending','ok','error','cancelled')),
    error_message       TEXT,
    prompt_tokens       INT,
    completion_tokens   INT,
    thinking_tokens     INT,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX messages_conv_id_idx ON messages(conversation_id, id);
CREATE UNIQUE INDEX messages_one_pending_per_conv
    ON messages(conversation_id) WHERE status='pending';

-- ============ Message Attachments ============
CREATE TABLE message_attachments (
    id            UUID PRIMARY KEY,
    user_id       UUID NOT NULL REFERENCES users(id),
    message_id    BIGINT REFERENCES messages(id) ON DELETE CASCADE,
    filename      TEXT NOT NULL,
    mime_type     TEXT NOT NULL,
    size_bytes    BIGINT NOT NULL,
    sha256        TEXT NOT NULL,
    storage_path  TEXT NOT NULL,
    created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX message_attachments_orphan_idx
    ON message_attachments(user_id, created_at) WHERE message_id IS NULL;
CREATE INDEX message_attachments_msg_idx
    ON message_attachments(message_id) WHERE message_id IS NOT NULL;

-- ============ LLM Usage ============
CREATE TABLE llm_usage (
    id                  BIGSERIAL PRIMARY KEY,
    conversation_id     UUID NOT NULL,
    message_id          BIGINT NOT NULL,
    user_id             UUID NOT NULL,
    endpoint_id         UUID NOT NULL,
    model_id            UUID NOT NULL,
    prompt_tokens       INT NOT NULL,
    completion_tokens   INT NOT NULL,
    thinking_tokens     INT NOT NULL DEFAULT 0,
    cost_usd            NUMERIC(10,6) NOT NULL,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX llm_usage_user_time_idx  ON llm_usage(user_id, created_at);
CREATE INDEX llm_usage_model_time_idx ON llm_usage(model_id, created_at);
CREATE INDEX llm_usage_time_idx       ON llm_usage(created_at);
