generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "darwin-arm64", "darwin", "windows", "debian-openssl-3.0.x", "linux-arm64-openssl-3.0.x", "debian-openssl-1.1.x"]
}

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

model Projects {
  id                   String                 @id @default(nanoid(12))
  name                 String
  description          String
  globalPrompt         String                 @default("")
  questionPrompt       String                 @default("")
  answerPrompt         String                 @default("")
  labelPrompt          String                 @default("")
  domainTreePrompt     String                 @default("")
  cleanPrompt          String                 @default("")
  defaultModelConfigId String?
  test                 String                 @default("")
  createAt             DateTime               @default(now())
  updateAt             DateTime               @updatedAt
  Questions            Questions[]
  Datasets             Datasets[]
  DatasetConversations DatasetConversations[]
  Chunks               Chunks[]
  ModelConfig          ModelConfig[]
  UploadFiles          UploadFiles[]
  Tags                 Tags[]
  Task                 Task[]
  GaPairs              GaPairs[]
  CustomPrompts        CustomPrompts[]
  Images               Images[]
  ImageDatasets        ImageDatasets[]
  QuestionTemplates    QuestionTemplates[]
  EvalDatasets         EvalDatasets[]
}

model UploadFiles {
  id        String    @id @default(nanoid())
  project   Projects  @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId String
  fileName  String
  fileExt   String
  path      String
  size      Int
  md5       String
  createAt  DateTime  @default(now())
  updateAt  DateTime  @updatedAt
  GaPairs   GaPairs[]
}

model Chunks {
  id           String         @id @default(nanoid())
  name         String
  project      Projects       @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId    String
  fileId       String
  fileName     String
  content      String
  summary      String
  size         Int
  createAt     DateTime       @default(now())
  updateAt     DateTime       @updatedAt
  Questions    Questions[]
  EvalDatasets EvalDatasets[]

  @@index([projectId])
}

model Tags {
  id        String   @id @default(nanoid())
  label     String
  project   Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId String
  parentId  String?
  parent    Tags?    @relation("Tags", fields: [parentId], references: [id])
  children  Tags[]   @relation("Tags")

  @@index([projectId, label])
  @@index([projectId, parentId])
}

model Questions {
  id         String   @id @default(nanoid())
  project    Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId  String
  chunk      Chunks   @relation(fields: [chunkId], references: [id])
  chunkId    String
  gaPair     GaPairs? @relation(fields: [gaPairId], references: [id])
  gaPairId   String? // Optional: links question to the GA pair that generated it
  question   String
  label      String
  answered   Boolean  @default(false)
  imageId    String? // Optional: for image-based questions
  imageName  String? // Optional: for image-based questions
  templateId String? // Optional: links to ImageQuestionTemplates
  createAt   DateTime @default(now())
  updateAt   DateTime @updatedAt

  @@index([projectId])
  @@index([imageId])
  @@index([templateId])
  @@index([projectId, label])
}

model Datasets {
  id            String   @id @default(nanoid())
  project       Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId     String
  questionId    String
  question      String
  answer        String
  answerType    String?  @default("text") // 'text' | 'label' | 'custom_format'
  chunkName     String
  chunkContent  String
  model         String
  questionLabel String
  cot           String
  confirmed     Boolean  @default(false)
  score         Float    @default(0)
  aiEvaluation  String   @default("") // AI评估结论
  tags          String   @default("")
  note          String   @default("")
  other         String   @default("") // 存储其他字段的JSON字符串
  createAt      DateTime @default(now())
  updateAt      DateTime @updatedAt

  @@index([projectId])
  @@index([projectId, confirmed, createAt, id], name: "idx_export_confirmed")
  @@index([projectId, createAt], name: "idx_project_createAt")
}

model DatasetConversations {
  id            String   @id @default(nanoid())
  project       Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId     String
  questionId    String // 第一个问题 Id（初始问题）
  question      String // 第一个问题（初始问题）
  chunkId       String // 基于哪个文本块生成
  model         String
  questionLabel String
  score         Float    @default(0)
  aiEvaluation  String   @default("") // AI评估结论
  tags          String   @default("")
  note          String   @default("")
  scenario      String // 对话场景（教学/咨询/讨论等）
  roleA         String // 角色A设定
  roleB         String // 角色B设定  
  turnCount     Int // 实际轮数
  maxTurns      Int // 设置的最大轮数
  rawMessages   String // JSON存储完整对话（和 ShareGPT 格式保持完全一致）
  confirmed     Boolean  @default(false)
  createAt      DateTime @default(now())
  updateAt      DateTime @updatedAt

  @@index([projectId])
}

model LlmProviders {
  id        String      @id
  name      String
  apiUrl    String
  createAt  DateTime    @default(now())
  updateAt  DateTime    @updatedAt
  LlmModels LlmModels[]
}

model LlmModels {
  id         String       @id @default(nanoid())
  modelId    String
  modelName  String
  provider   LlmProviders @relation(fields: [providerId], references: [id])
  providerId String
  createAt   DateTime     @default(now())
  updateAt   DateTime     @updatedAt
}

model ModelConfig {
  id           String   @id @default(nanoid())
  project      Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId    String
  providerId   String
  providerName String
  endpoint     String
  apiKey       String
  modelId      String
  modelName    String
  type         String
  temperature  Float
  maxTokens    Int
  topP         Float
  topK         Float
  status       Int
  createAt     DateTime @default(now())
  updateAt     DateTime @updatedAt
}

model Task {
  id             String    @id @default(nanoid())
  project        Projects  @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId      String
  taskType       String // 任务类型: text-processing, question-generation, answer-generation, data-distillation
  status         Int // 任务状态: 0-处理中, 1-已完成, 2-失败, 3-已中断
  startTime      DateTime  @default(now())
  endTime        DateTime?
  completedCount Int       @default(0)
  totalCount     Int       @default(0)
  modelInfo      String // JSON格式存储，包含使用的模型信息
  language       String    @default("zh-CN")
  detail         String    @default("") // 任务详情
  note           String    @default("") // 任务备注
  createAt       DateTime  @default(now())
  updateAt       DateTime  @updatedAt

  @@index([projectId])
}

model CustomPrompts {
  id         String   @id @default(nanoid())
  project    Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId  String
  promptType String // 提示词类型，对应 lib/llm/prompts 下的文件名
  promptKey  String // 提示词在模块中的键名，如 QUESTION_PROMPT, QUESTION_PROMPT_EN
  language   String // 语言: zh-CN, en
  content    String // 自定义的提示词内容
  isActive   Boolean  @default(true) // 是否启用
  createAt   DateTime @default(now())
  updateAt   DateTime @updatedAt

  @@unique([projectId, promptType, promptKey, language])
  @@index([projectId, promptType])
  @@index([projectId, language])
}

model GaPairs {
  id            String      @id @default(nanoid())
  project       Projects    @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId     String
  uploadFile    UploadFiles @relation(fields: [fileId], references: [id], onDelete: Cascade)
  fileId        String
  pairNumber    Int // 1-5, representing the 5 generated pairs
  genreTitle    String // Genre name/title
  genreDesc     String // Genre description
  audienceTitle String // Audience name/title  
  audienceDesc  String // Audience description
  isActive      Boolean     @default(true) // Whether this pair is active for use
  questions     Questions[] // Questions generated by this GA pair
  createAt      DateTime    @default(now())
  updateAt      DateTime    @updatedAt

  @@unique([fileId, pairNumber])
  @@index([projectId])
  @@index([fileId])
}

model Images {
  id            String          @id @default(nanoid())
  project       Projects        @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId     String
  imageName     String
  path          String // 图片存储路径
  size          Int // 文件大小（字节）
  width         Int? // 图片宽度
  height        Int? // 图片高度
  createAt      DateTime        @default(now())
  updateAt      DateTime        @updatedAt
  ImageDatasets ImageDatasets[]

  @@unique([projectId, imageName])
  @@index([projectId])
}

model ImageDatasets {
  id         String   @id @default(nanoid())
  project    Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId  String
  image      Images   @relation(fields: [imageId], references: [id], onDelete: Cascade)
  imageId    String
  imageName  String
  questionId String? // Optional: links to Questions table
  question   String
  answer     String // Stores all answer types: text, JSON array for labels, or custom format JSON
  answerType String   @default("text") // 'text' | 'label' | 'custom_format'
  model      String
  confirmed  Boolean  @default(false)
  score      Float    @default(0)
  tags       String   @default("")
  note       String   @default("")
  createAt   DateTime @default(now())
  updateAt   DateTime @updatedAt

  @@index([projectId])
  @@index([imageId])
  @@index([questionId])
}

model QuestionTemplates {
  id           String   @id @default(nanoid())
  project      Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId    String
  question     String // Question content
  sourceType   String // 'image' | 'text' - data source type
  answerType   String // 'text' | 'label' | 'custom_format'
  description  String   @default("") // Question description
  labels       String   @default("") // JSON array of label options (for answerType='label')
  customFormat String   @default("") // Custom format definition (for answerType='custom_format')
  order        Int      @default(0) // Display order
  createAt     DateTime @default(now())
  updateAt     DateTime @updatedAt

  @@index([projectId])
  @@index([projectId, sourceType])
}

model LlmUsageLogs {
  id        String @id @default(nanoid())
  projectId String
  provider  String // 提供商: openai, anthropic, google 等
  model     String // 模型名称

  // 核心指标
  inputTokens  Int @default(0)
  outputTokens Int @default(0)
  totalTokens  Int @default(0)
  latency      Int @default(0) // 响应耗时（毫秒）

  // 状态与追踪
  status       String  @default("SUCCESS") // 状态: "SUCCESS", "FAILED"
  errorMessage String? // 失败原因，status="FAILED" 时填写

  // 时间维度
  createAt   DateTime @default(now())
  dateString String // 格式 "YYYY-MM-DD"，用于快速按天聚合

  @@index([projectId, dateString])
  @@index([dateString])
  @@index([provider])
  @@index([model])
}

model EvalDatasets {
  id        String   @id @default(nanoid())
  project   Projects @relation(fields: [projectId], references: [id], onDelete: Cascade)
  projectId String

  // 题目内容
  question     String // 题目内容
  questionType String // 题型: true_false, single_choice, multiple_choice, short_answer, open_ended

  // 上下文信息（关联到文本块）
  chunkId String? // 关联到 Chunks 表
  chunks  Chunks? @relation(fields: [chunkId], references: [id])

  // 选项（仅选择题使用）
  options String @default("") // JSON数组: ["选项A", "选项B", "选项C", "选项D"]

  // 标准答案
  correctAnswer String // 标准答案

  tags String @default("") // 标签，逗号分隔
  note String @default("") // 备注

  // 时间戳
  createAt DateTime @default(now())
  updateAt DateTime @updatedAt

  // 关联评估结果
  EvalResults EvalResults[]

  @@index([projectId])
  @@index([projectId, questionType])
  @@index([chunkId])
}

model EvalResults {
  id        String @id @default(nanoid())
  projectId String
  taskId    String // 关联到 Task 表

  // 关联评估题目
  evalDataset   EvalDatasets @relation(fields: [evalDatasetId], references: [id], onDelete: Cascade)
  evalDatasetId String

  // 评估结果
  modelAnswer   String // 模型的回答
  score         Float   @default(0) // 得分 (0-1 之间)
  isCorrect     Boolean @default(false) // 是否正确（用于客观题）
  judgeResponse String  @default("") // LLM 评分的响应（用于主观题）

  // 答题详情
  duration     Int    @default(0) // 答题耗时（毫秒）
  status       Int    @default(0) // 答题状态：0-成功, 1-输出不符合规范, 2-LLM调用报错
  errorMessage String @default("") // 答题报错信息

  // 时间戳
  createAt DateTime @default(now())
  updateAt DateTime @updatedAt

  @@unique([taskId, evalDatasetId]) // 每个任务对每道题只能有一个结果
  @@index([projectId])
  @@index([taskId])
  @@index([evalDatasetId])
}
