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

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

enum RecurrenceType {
  hourly
  daily
  weekly
  monthly
  yearly
}

enum TargetType {
  todo
  reminder_task
}

enum ChannelType {
  inapp
  bark
}

enum NotificationStatus {
  pending
  queued
  sent
  failed
}

model User {
  id             String   @id @default(cuid())
  username       String   @unique
  passwordHash   String
  avatar         String?
  timezone       String   @default("Asia/Shanghai")
  barkUrl        String?
  inappEnabled   Boolean  @default(true)
  barkEnabled    Boolean  @default(false)
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

  invites        Invite[] @relation("InviteCreator")
  todos          Todo[]   @relation("TodoOwner")
  createdTasks   ReminderTask[] @relation("TaskCreator")
  taskRecipients ReminderTaskRecipient[]
  notifications  Notification[] @relation("NotificationRecipient")
}

model Invite {
  id        String   @id @default(cuid())
  code      String   @unique
  creatorId String
  maxUses   Int      @default(5)
  usedCount Int      @default(0)
  expiresAt DateTime
  revokedAt DateTime?
  createdAt DateTime @default(now())

  creator   User     @relation("InviteCreator", fields: [creatorId], references: [id])

  @@index([creatorId])
  @@index([expiresAt])
}

model RecurrenceRule {
  id         String   @id @default(cuid())
  type       RecurrenceType
  interval   Int      @default(1)
  byWeekday  Int?
  byMonthday Int?
  timezone   String   @default("Asia/Shanghai")
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  todos      Todo[]
  tasks      ReminderTask[]
}

model Todo {
  id               String   @id @default(cuid())
  ownerId          String
  title            String
  description      String?
  dueAt            DateTime
  recurrenceRuleId String?
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt

  owner            User     @relation("TodoOwner", fields: [ownerId], references: [id])
  recurrenceRule   RecurrenceRule? @relation(fields: [recurrenceRuleId], references: [id])

  @@index([ownerId, dueAt])
  @@index([recurrenceRuleId])
}

model ReminderTask {
  id               String   @id @default(cuid())
  creatorId        String
  title            String
  description      String?
  dueAt            DateTime
  recurrenceRuleId String?
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt

  creator          User     @relation("TaskCreator", fields: [creatorId], references: [id])
  recurrenceRule   RecurrenceRule? @relation(fields: [recurrenceRuleId], references: [id])
  recipients       ReminderTaskRecipient[]

  @@index([creatorId, dueAt])
  @@index([recurrenceRuleId])
}

model ReminderTaskRecipient {
  taskId String
  userId String

  task   ReminderTask @relation(fields: [taskId], references: [id])
  user   User         @relation(fields: [userId], references: [id])

  @@id([taskId, userId])
  @@index([userId])
}

model ReminderOffset {
  id           String   @id @default(cuid())
  targetType   TargetType
  targetId     String
  offsetMinutes Int
  channelInapp Boolean  @default(true)
  channelBark  Boolean  @default(false)
  createdAt    DateTime @default(now())

  @@index([targetType, targetId])
}

model Notification {
  id           String             @id @default(cuid())
  recipientId  String
  targetType   TargetType
  targetId     String
  triggerAt    DateTime
  channel      ChannelType
  status       NotificationStatus @default(pending)
  lockedAt     DateTime?
  sentAt       DateTime?
  readAt       DateTime?
  createdAt    DateTime           @default(now())
  updatedAt    DateTime           @updatedAt

  recipient    User               @relation("NotificationRecipient", fields: [recipientId], references: [id])
  logs         DeliveryLog[]

  @@unique([recipientId, targetType, targetId, triggerAt, channel])
  @@index([status, triggerAt])
  @@index([recipientId, readAt])
}

model DeliveryLog {
  id             String   @id @default(cuid())
  notificationId String
  attemptNo      Int
  channel        ChannelType
  status         NotificationStatus
  responseMeta   Json?
  createdAt      DateTime @default(now())

  notification   Notification @relation(fields: [notificationId], references: [id])

  @@index([notificationId])
}
