// chat-service's own Prisma schema, pointed at its own database (chat_bot) —
// deliberately separate from prisma/schema.prisma at the repo root (the cart
// platform's DB). Model shapes match the SQL already applied via
// prisma/migrations/manual/001_init_chat_schema.sql and 002_add_last_seen_and_receipts.sql.

generator client {
  provider        = "prisma-client-js"
  output          = "../node_modules/.prisma/chat-client"
  previewFeatures = ["multiSchema"]
  binaryTargets   = ["native", "rhel-openssl-3.0.x", "rhel-openssl-1.1.x"]
}

datasource db {
  provider = "postgresql"
  url      = env("CHAT_DATABASE_URL")
  schemas  = ["chat"]
}

enum ApplicationStatus {
  active
  suspended

  @@schema("chat")
}

// Lifecycle only — open|closed. Who's currently answering (bot vs agent) is
// the separate ChatSessionMode below; conflating the two used to make
// escalation a permanent, one-way trip (see migration 005's note).
enum ChatSessionStatus {
  open
  closed

  @@schema("chat")
}

enum ChatSessionMode {
  bot
  agent

  @@schema("chat")
}

enum ChatMessageRole {
  user
  assistant
  system
  agent

  @@schema("chat")
}

enum ServiceRequestStatus {
  open
  assigned
  in_progress
  in_review
  closed
  reopened

  @@schema("chat")
}

enum ServiceRequestPriority {
  low
  medium
  high
  critical

  @@schema("chat")
}

enum ServiceRequestCategory {
  order
  delivery
  payment
  general

  @@schema("chat")
}

enum ServiceRequestEventType {
  created
  assigned
  status_changed
  transferred
  note_added
  closed
  reopened

  @@schema("chat")
}

model Application {
  id             String            @id @default(uuid())
  slug           String            @unique
  name           String
  status         ApplicationStatus @default(active)
  allowedOrigins String[]
  // The cart-platform store this application serves — the escalation-routing
  // key: an admin whose JWT storeId matches acts as this application's agent.
  externalStoreId String?          @unique @map("external_store_id")
  settings       Json              @default("{}")
  isActive       Boolean           @default(true)
  sortOrder      Int               @default(0)
  createdBy      String            @default("system")
  createdOn      DateTime          @default(now())
  updatedBy      String            @default("system")
  updatedOn      DateTime          @default(now()) @updatedAt
  deletedAt      DateTime?
  deletedBy      String?

  apiKeys         ApiKey[]
  sessions        ChatSession[]
  knowledge       KnowledgeEntry[]
  serviceRequests ServiceRequest[]

  @@map("applications")
  @@schema("chat")
}

model ApiKey {
  id            String    @id @default(uuid())
  applicationId String
  application   Application @relation(fields: [applicationId], references: [id])
  keyHash       String    @unique
  label         String
  lastUsedAt    DateTime?
  revokedAt     DateTime?
  createdBy     String    @default("system")
  createdOn     DateTime  @default(now())
  updatedBy     String    @default("system")
  updatedOn     DateTime  @default(now()) @updatedAt

  @@map("api_keys")
  @@schema("chat")
}

model ChatSession {
  id                    String            @id @default(uuid())
  applicationId         String
  application           Application @relation(fields: [applicationId], references: [id])
  externalUserId        String?
  externalUserName      String?
  externalUserEmail     String?
  externalIdentityGroup String?
  status                ChatSessionStatus @default(open)
  mode                  ChatSessionMode   @default(bot)
  responderKey          String?
  startedAt             DateTime          @default(now())
  lastMessageAt         DateTime          @default(now())
  lastSeenAt            DateTime?
  closedAt              DateTime?
  createdBy             String            @default("system")
  createdOn             DateTime          @default(now())
  updatedBy             String            @default("system")
  updatedOn             DateTime          @default(now()) @updatedAt

  messages       ChatMessage[]
  serviceRequest ServiceRequest?

  @@map("chat_sessions")
  @@schema("chat")
}

model ChatMessage {
  id          String   @id @default(uuid())
  sessionId   String
  session     ChatSession @relation(fields: [sessionId], references: [id])
  role        ChatMessageRole
  content     String
  metadata    Json?
  deliveredAt DateTime?
  readAt      DateTime?
  createdBy   String   @default("system")
  createdOn   DateTime @default(now())
  updatedBy   String   @default("system")
  updatedOn   DateTime @default(now()) @updatedAt

  @@map("chat_messages")
  @@schema("chat")
}

// A ServiceRequest is created when a ChatSession is escalated — it's a
// strict 1:1 wrapper around the session that adds ticket-workflow concepts
// (number, status, priority, category, assignment) the raw session doesn't
// have. A customer may have at most one non-closed ServiceRequest per
// application at a time (enforced in ChatService.escalate(), not here).
model ServiceRequest {
  id                String                 @id @default(uuid())
  srNumber          Int                    @unique @default(autoincrement()) @map("sr_number")
  applicationId     String
  application       Application            @relation(fields: [applicationId], references: [id])
  sessionId         String                 @unique
  session           ChatSession            @relation(fields: [sessionId], references: [id])
  externalUserId    String?
  externalUserName  String?
  externalUserEmail String?
  status            ServiceRequestStatus   @default(open)
  priority          ServiceRequestPriority @default(medium)
  category          ServiceRequestCategory @default(general)
  assignedAgentId   String?
  assignedAgentName String?
  createdBy         String                 @default("system")
  createdOn         DateTime               @default(now())
  updatedBy         String                 @default("system")
  updatedOn         DateTime               @default(now()) @updatedAt
  closedAt          DateTime?

  events ServiceRequestEvent[]
  notes  ServiceRequestNote[]

  @@index([applicationId])
  @@index([applicationId, externalUserId])
  @@map("service_requests")
  @@schema("chat")
}

// Append-only audit trail — one row per status change / assignment /
// transfer / note. Rendered as the "Service Request Timeline" in the admin UI.
model ServiceRequestEvent {
  id               String                  @id @default(uuid())
  serviceRequestId String
  serviceRequest   ServiceRequest          @relation(fields: [serviceRequestId], references: [id])
  type             ServiceRequestEventType
  fromValue        String?
  toValue          String?
  actorId          String?
  actorName        String?
  createdOn        DateTime                @default(now())

  @@index([serviceRequestId])
  @@map("service_request_events")
  @@schema("chat")
}

// Agent-only notes — kept in their own table (not ChatMessage rows with a
// flag) so the shopper-facing message endpoints never need an internal/
// external filter, and so they render in their own panel, per spec.
model ServiceRequestNote {
  id               String         @id @default(uuid())
  serviceRequestId String
  serviceRequest   ServiceRequest @relation(fields: [serviceRequestId], references: [id])
  authorId         String
  authorName       String
  content          String
  createdOn        DateTime       @default(now())

  @@index([serviceRequestId])
  @@map("service_request_notes")
  @@schema("chat")
}

model KnowledgeEntry {
  id            String   @id @default(uuid())
  applicationId String
  application   Application @relation(fields: [applicationId], references: [id])
  question      String
  answer        String
  keywords      String[]
  // Tappable links a reply using this entry carries (e.g. straight to an
  // order/policy/product page) — [{label, url}], never bare strings, so the
  // widget doesn't have to guess display text. Defaults to an empty array,
  // not null, so every reader can iterate it unconditionally.
  links         Json     @default("[]")
  isActive      Boolean  @default(true)
  sortOrder     Int      @default(0)
  createdBy     String   @default("system")
  createdOn     DateTime @default(now())
  updatedBy     String   @default("system")
  updatedOn     DateTime @default(now()) @updatedAt

  @@map("knowledge_entries")
  @@schema("chat")
}
