// Prisma schema for the personal chat DB + LLM call log

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

enum Provider {
  openai
  anthropic
  xai
  hermes_agent @map("hermes-agent")
}

enum MessageRole {
  system
  user
  assistant
  tool
}

enum SearchSource {
  exa
}

enum ProjectKind {
  starred
  folder
}

model User {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  // minimal for now (single-user is fine). Keep extensible.
  handle String? @unique

  chats Chat[]
  searches Search[]
  projects Project[]
}

model Chat {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  title String?

  initiatedProvider Provider?
  initiatedModel    String?
  lastUsedProvider  Provider?
  lastUsedModel     String?

  additionalSystemPrompt String?
  enabledTools           Json?

  user   User?   @relation(fields: [userId], references: [id])
  userId String?

  messages Message[]
  calls    LlmCall[]
  projectItems ProjectItem[]

  @@index([userId])
}

model Message {
  id        String      @id @default(cuid())
  createdAt DateTime    @default(now())

  chat   Chat   @relation(fields: [chatId], references: [id], onDelete: Cascade)
  chatId String

  role    MessageRole
  content String

  // for tool messages or attachments later
  name     String?
  metadata Json?

  @@index([chatId, createdAt])
}

model LlmCall {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())

  chat   Chat   @relation(fields: [chatId], references: [id], onDelete: Cascade)
  chatId String

  provider Provider
  model    String

  // request/response snapshots for debugging + replay
  request  Json
  response Json?

  // usage/cost basics
  inputTokens  Int?
  outputTokens Int?
  totalTokens  Int?

  latencyMs Int?

  error   String?

  @@index([chatId, createdAt])
  @@index([provider, model, createdAt])
}

model Search {
  id        String       @id @default(cuid())
  createdAt DateTime     @default(now())
  updatedAt DateTime     @updatedAt

  title String?
  query String?
  queryNormalized String?

  source SearchSource @default(exa)

  requestId   String?
  rawResponse Json?
  latencyMs   Int?
  error       String?

  answerText        String?
  answerRequestId   String?
  answerCitations   Json?
  answerRawResponse Json?
  answerError       String?

  user   User?   @relation(fields: [userId], references: [id])
  userId String?

  results SearchResult[]
  projectItems ProjectItem[]

  @@index([updatedAt])
  @@index([queryNormalized, updatedAt])
  @@index([userId])
}

model SearchResult {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())

  search   Search @relation(fields: [searchId], references: [id], onDelete: Cascade)
  searchId String

  rank Int

  title         String?
  url           String
  publishedDate String?
  author        String?
  text          String?
  highlights    Json?
  highlightScores Json?
  score         Float?
  favicon       String?
  image         String?

  @@index([searchId, rank])
}

model Project {
  id        String      @id @default(cuid())
  createdAt DateTime    @default(now())
  updatedAt DateTime    @updatedAt

  kind  ProjectKind @default(folder)
  title String

  user   User?   @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId String?

  items ProjectItem[]

  @@index([kind])
  @@index([userId])
}

model ProjectItem {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())

  project   Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId String

  chat   Chat?   @relation(fields: [chatId], references: [id], onDelete: Cascade)
  chatId String?

  search   Search? @relation(fields: [searchId], references: [id], onDelete: Cascade)
  searchId String?

  @@unique([projectId, chatId])
  @@unique([projectId, searchId])
  @@index([projectId, createdAt])
  @@index([chatId])
  @@index([searchId])
}
