generator client {
  provider = "prisma-client-js"
  output   = "../src/generated/prisma"
}

datasource db {
  provider = "postgresql"
}

enum UserStatus {
  ACTIVE
  SUSPENDED
  DELETED
}

enum SessionStatus {
  ACTIVE
  LOCKED
  REVOKED
  EXPIRED
}

enum DeviceType {
  WEB
  IOS
  ANDROID
  DESKTOP
  TV
  SMART_SPEAKER
  OTHER
}

enum OAuthClientType {
  CONFIDENTIAL
  PUBLIC
}

model User {
  id              String          @id @default(uuid())
  email           String?         @unique
  phone           String?         @unique
  backupEmail     String?         @unique
  backupPhone     String?         @unique
  passwordHash    String?
  displayName     String
  username        String?         @unique
  avatarUrl       String?
  avatarStorageKey String?
  birthDate       DateTime?
  gender          String?
  isSuperAdmin    Boolean         @default(false)
  status          UserStatus      @default(ACTIVE)
  createdAt       DateTime        @default(now())
  updatedAt       DateTime        @updatedAt
  deletedAt       DateTime?
  deletionRequestedAt DateTime?
  pinCode         PinCode?
  sessions        Session[]
  devices         Device[]
  signInEvents    SignInEvent[]
  authCodes       AuthCode[]
  linkedAccounts  LinkedAccount[]
  userRoles       UserRole[]
  userPermissions UserPermission[]
  profile         UserProfile?
  documents       UserDocument[]
  addresses       Address[]
  oauthConsents   OAuthConsent[]
  oauthAuthCodes  OAuthAuthorizationCode[]
  ownedFamilyGroups FamilyGroup[]
  familyMemberships FamilyMember[]
  sentFamilyInvites FamilyInvite[] @relation("FamilyInviteInviter")
  receivedFamilyInvites FamilyInvite[] @relation("FamilyInviteInvitee")
  notifications Notification[]
  chatRoomMembers ChatRoomMember[]
  chatMessages ChatMessage[]
  chatPollVotes ChatPollVote[]
  totpSecret    UserTotpSecret?
  createdOAuthClients OAuthClient[] @relation("OAuthClientCreator")
}

model UserTotpSecret {
  id        String   @id @default(uuid())
  userId    String   @unique
  secretEnc String
  isEnabled Boolean  @default(false)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model UserProfile {
  id        String   @id @default(uuid())
  userId    String   @unique
  firstName String?
  lastName  String?
  bio       String?
  age       Int?
  gender    String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model PinCode {
  id                  String    @id @default(uuid())
  userId              String    @unique
  hash                String
  isEnabled           Boolean   @default(false)
  deletionRequestedAt DateTime?
  createdAt           DateTime  @default(now())
  updatedAt           DateTime  @updatedAt
  user                User      @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Session {
  id          String        @id @default(uuid())
  userId      String
  deviceId    String?
  refreshHash String
  pinVerified Boolean       @default(true)
  status      SessionStatus @default(ACTIVE)
  ipAddress   String?
  userAgent   String?
  expiresAt   DateTime
  createdAt   DateTime      @default(now())
  updatedAt   DateTime      @updatedAt
  user        User          @relation(fields: [userId], references: [id], onDelete: Cascade)
  device      Device?       @relation(fields: [deviceId], references: [id], onDelete: SetNull)

  @@index([userId, status])
}

model Device {
  id           String        @id @default(uuid())
  userId       String
  name         String
  type         DeviceType    @default(OTHER)
  fingerprint  String
  lastIp       String?
  lastSeenAt   DateTime      @default(now())
  trusted      Boolean       @default(false)
  createdAt    DateTime      @default(now())
  user         User          @relation(fields: [userId], references: [id], onDelete: Cascade)
  sessions     Session[]
  signInEvents SignInEvent[]

  @@unique([userId, fingerprint])
}

model SignInEvent {
  id        String   @id @default(uuid())
  userId    String
  deviceId  String?
  ipAddress String?
  userAgent String?
  success   Boolean
  reason    String?
  createdAt DateTime @default(now())
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  device    Device?  @relation(fields: [deviceId], references: [id], onDelete: SetNull)

  @@index([userId, createdAt])
}

model LinkedAccount {
  id           String   @id @default(uuid())
  userId       String
  providerName String
  providerId   String
  email        String?
  displayName  String?
  avatarUrl    String?
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([providerName, providerId])
  @@index([userId])
}

model Role {
  id          String           @id @default(uuid())
  slug        String           @unique
  name        String
  description String?
  isSystem    Boolean          @default(false)
  isDefault   Boolean          @default(false)
  createdAt   DateTime         @default(now())
  updatedAt   DateTime         @updatedAt
  users       UserRole[]
  permissions RolePermission[]
}

model Permission {
  id          String           @id @default(uuid())
  slug        String           @unique
  name        String
  description String?
  createdAt   DateTime         @default(now())
  roles       RolePermission[]
  users       UserPermission[]
}

model UserPermission {
  userId       String
  permissionId String
  createdAt    DateTime   @default(now())
  user         User       @relation(fields: [userId], references: [id], onDelete: Cascade)
  permission   Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)

  @@id([userId, permissionId])
}

model UserRole {
  userId    String
  roleId    String
  createdAt DateTime @default(now())
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  role      Role     @relation(fields: [roleId], references: [id], onDelete: Cascade)

  @@id([userId, roleId])
}

model RolePermission {
  roleId       String
  permissionId String
  createdAt    DateTime   @default(now())
  role         Role       @relation(fields: [roleId], references: [id], onDelete: Cascade)
  permission   Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)

  @@id([roleId, permissionId])
}

model OAuthClient {
  id           String           @id @default(uuid())
  name         String
  clientId     String           @unique
  clientSecret String?
  type         OAuthClientType   @default(CONFIDENTIAL)
  redirectUris String[]
  scopes       OAuthClientScope[]
  isActive     Boolean          @default(true)
  createdById  String?
  createdAt    DateTime         @default(now())
  updatedAt    DateTime         @updatedAt
  createdBy    User?            @relation("OAuthClientCreator", fields: [createdById], references: [id], onDelete: SetNull)
  consents     OAuthConsent[]
  authCodes    OAuthAuthorizationCode[]

  @@index([createdById])
}

model OAuthAuthorizationCode {
  id          String      @id @default(uuid())
  code        String      @unique
  userId      String
  clientId    String
  redirectUri String
  scopes      String[]
  expiresAt   DateTime
  consumedAt  DateTime?
  createdAt   DateTime    @default(now())
  user        User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  client      OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)

  @@index([userId, clientId])
}

model OAuthScope {
  id          String             @id @default(uuid())
  slug        String             @unique
  name        String
  description String?
  clients     OAuthClientScope[]
  consents    OAuthConsentScope[]
}

model OAuthClientScope {
  clientId String
  scopeId  String
  client   OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
  scope    OAuthScope  @relation(fields: [scopeId], references: [id], onDelete: Cascade)

  @@id([clientId, scopeId])
}

model OAuthConsent {
  id        String              @id @default(uuid())
  userId    String
  clientId  String
  createdAt DateTime            @default(now())
  updatedAt DateTime            @updatedAt
  user      User                @relation(fields: [userId], references: [id], onDelete: Cascade)
  client    OAuthClient         @relation(fields: [clientId], references: [id], onDelete: Cascade)
  scopes    OAuthConsentScope[]

  @@unique([userId, clientId])
}

model OAuthConsentScope {
  consentId String
  scopeId   String
  consent   OAuthConsent @relation(fields: [consentId], references: [id], onDelete: Cascade)
  scope     OAuthScope   @relation(fields: [scopeId], references: [id], onDelete: Cascade)

  @@id([consentId, scopeId])
}

model UserDocument {
  id        String   @id @default(uuid())
  userId    String
  type      String
  number    String
  issuedAt  DateTime?
  expiresAt DateTime?
  metadata  Json?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model AuthCode {
  id        String    @id @default(uuid())
  userId    String?
  channel   String
  target    String
  codeHash  String
  purpose   String
  expiresAt DateTime
  usedAt    DateTime?
  createdAt DateTime  @default(now())
  user      User?     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([target, purpose, expiresAt])
}

model FamilyGroup {
  id               String         @id @default(uuid())
  ownerId          String
  name             String
  avatarStorageKey String?
  hasAvatar        Boolean        @default(false)
  createdAt        DateTime       @default(now())
  updatedAt        DateTime       @updatedAt
  owner            User           @relation(fields: [ownerId], references: [id], onDelete: Cascade)
  members          FamilyMember[]
  invites          FamilyInvite[]
  chatRooms        ChatRoom[]
}

model FamilyInvite {
  id            String      @id @default(uuid())
  groupId       String
  inviterId     String
  inviteeUserId String?
  targetEmail   String?
  targetPhone   String?
  status        String      @default("PENDING")
  token         String      @unique @default(uuid())
  expiresAt     DateTime
  createdAt     DateTime    @default(now())
  updatedAt     DateTime    @updatedAt
  group         FamilyGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
  inviter       User        @relation("FamilyInviteInviter", fields: [inviterId], references: [id], onDelete: Cascade)
  invitee       User?       @relation("FamilyInviteInvitee", fields: [inviteeUserId], references: [id], onDelete: SetNull)

  @@index([inviteeUserId, status])
  @@index([groupId, status])
}

model Notification {
  id        String   @id @default(uuid())
  userId    String
  type      String
  title     String
  message   String
  payload   Json?
  isRead    Boolean  @default(false)
  createdAt DateTime @default(now())
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId, isRead, createdAt])
}

model ChatRoom {
  id               String           @id @default(uuid())
  groupId          String
  type             String
  name             String
  avatarStorageKey String?
  hasAvatar        Boolean          @default(false)
  createdById      String?
  createdAt        DateTime         @default(now())
  updatedAt        DateTime         @updatedAt
  group            FamilyGroup      @relation(fields: [groupId], references: [id], onDelete: Cascade)
  members          ChatRoomMember[]
  messages         ChatMessage[]

  @@index([groupId, type])
}

model ChatRoomMember {
  id                 String   @id @default(uuid())
  roomId             String
  userId             String
  notificationsMuted Boolean   @default(false)
  lastReadAt         DateTime?
  lastReadMessageId  String?
  joinedAt           DateTime  @default(now())
  room               ChatRoom @relation(fields: [roomId], references: [id], onDelete: Cascade)
  user               User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([roomId, userId])
}

model ChatMessage {
  id         String     @id @default(uuid())
  roomId     String
  senderId   String
  type       String
  content    String?
  replyToId  String?
  metadata   Json?
  storageKey String?
  mimeType   String?
  createdAt  DateTime   @default(now())
  editedAt   DateTime?
  deletedAt  DateTime?
  room       ChatRoom   @relation(fields: [roomId], references: [id], onDelete: Cascade)
  sender     User       @relation(fields: [senderId], references: [id], onDelete: Cascade)
  poll       ChatPoll?

  @@index([roomId, createdAt])
}

model ChatPoll {
  id             String           @id @default(uuid())
  messageId      String           @unique
  question       String
  allowsMultiple Boolean          @default(false)
  isAnonymous    Boolean          @default(false)
  closedAt       DateTime?
  message        ChatMessage      @relation(fields: [messageId], references: [id], onDelete: Cascade)
  options        ChatPollOption[]
}

model ChatPollOption {
  id     String         @id @default(uuid())
  pollId String
  text   String
  poll   ChatPoll       @relation(fields: [pollId], references: [id], onDelete: Cascade)
  votes  ChatPollVote[]
}

model ChatPollVote {
  id       String         @id @default(uuid())
  optionId String
  userId   String
  option   ChatPollOption @relation(fields: [optionId], references: [id], onDelete: Cascade)
  user     User           @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([optionId, userId])
}

model FamilyMember {
  id        String      @id @default(uuid())
  groupId   String
  userId    String
  role      String      @default("member")
  createdAt DateTime    @default(now())
  group     FamilyGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
  user      User        @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([groupId, userId])
}

model Address {
  id          String   @id @default(uuid())
  userId      String
  label       String
  city        String
  street      String
  house       String
  apartment   String?
  comment     String?
  latitude    Float?
  longitude   Float?
  fullAddress String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId, label])
}

model SystemSetting {
  id          String   @id @default(uuid())
  key         String   @unique
  value       String
  description String?
  isSecret    Boolean  @default(false)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model SocialProvider {
  id           String   @id @default(uuid())
  providerName String   @unique
  clientId     String
  clientSecret String?
  isEnabled    Boolean  @default(false)
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
}
