// EN: Enterprise IAM Service Prisma Schema
// VI: Schema Prisma cho Enterprise IAM Service

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

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

// EN: User model - Core user entity
// VI: Model User - Entity người dùng cốt lõi
model User {
  id                  String    @id @default(cuid())
  email               String    @unique
  username            String?   @unique
  passwordHash        String? // Nullable for social-only users
  isActive            Boolean   @default(true)
  emailVerified       Boolean   @default(false)
  mfaEnabled          Boolean   @default(false)
  mfaSecret           String?   // Encrypted TOTP secret
  mfaBackupCodes      String?   @db.Text // Encrypted JSON array of backup codes
  lastLoginAt         DateTime?
  loginCount          Int       @default(0)
  failedLoginAttempts Int       @default(0) // Track failed login attempts for lockout
  lockedUntil         DateTime? // Account lockout timestamp
  organizationId      String?
  createdAt           DateTime  @default(now())
  updatedAt           DateTime  @updatedAt

  // Existing Relations
  userRoles       UserRole[]
  userPermissions UserPermission[]
  sessions        Session[]
  refreshTokens   RefreshToken[]
  socialAccounts  SocialAccount[]
  mfaDevices      MFADevice[]
  authEvents      AuthEvent[]

  // New IAM Relations
  organization   Organization?          @relation(fields: [organizationId], references: [id])
  profile        UserProfile?
  verifications  IdentityVerification[]
  accessRequests AccessRequest[]
  riskScores     RiskScore[]
  groupMembers   GroupMember[]

  @@index([email])
  @@index([username])
  @@index([createdAt])
  @@index([organizationId])
  @@map("users")
}

// EN: Role model - RBAC roles
// VI: Model Role - Vai trò RBAC
model Role {
  id          String   @id @default(cuid())
  name        String   @unique // ADMIN, MANAGER, USER, etc.
  displayName String
  description String?
  isSystem    Boolean  @default(false) // Cannot be deleted
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  // Relations
  permissions RolePermission[]
  userRoles   UserRole[]

  @@map("roles")
}

// EN: Permission model - Granular permissions
// VI: Model Permission - Quyền chi tiết
model Permission {
  id          String   @id @default(cuid())
  resource    String // users, products, orders, etc.
  action      String // create, read, update, delete, etc.
  scope       String? // own, team, all
  description String?
  createdAt   DateTime @default(now())

  // Relations
  roles  RolePermission[]
  users  UserPermission[]
  groups GroupPermission[]

  @@unique([resource, action, scope])
  @@index([resource])
  @@index([resource, action])
  @@map("permissions")
}

// EN: UserRole - Many-to-many relationship with expiration
// VI: UserRole - Quan hệ nhiều-nhiều với thời hạn
model UserRole {
  id        String    @id @default(cuid())
  userId    String
  roleId    String
  grantedBy String? // ID of user who granted this role
  expiresAt DateTime? // Temporary role assignment
  createdAt DateTime  @default(now())

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)

  @@unique([userId, roleId])
  @@index([userId])
  @@index([roleId])
  @@index([expiresAt])
  @@map("user_roles")
}

// EN: RolePermission - Many-to-many relationship
// VI: RolePermission - Quan hệ nhiều-nhiều
model RolePermission {
  id           String   @id @default(cuid())
  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)

  @@unique([roleId, permissionId])
  @@index([roleId])
  @@map("role_permissions")
}

// EN: UserPermission - Direct user permissions (override roles)
// VI: UserPermission - Quyền trực tiếp của người dùng (ghi đè roles)
model UserPermission {
  id           String    @id @default(cuid())
  userId       String
  permissionId String
  granted      Boolean   @default(true) // false = deny permission
  grantedBy    String?
  expiresAt    DateTime?
  createdAt    DateTime  @default(now())

  user       User       @relation(fields: [userId], references: [id], onDelete: Cascade)
  permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)

  @@unique([userId, permissionId])
  @@index([userId])
  @@index([expiresAt])
  @@map("user_permissions")
}

// EN: Session model - Active user sessions
// VI: Model Session - Phiên người dùng đang hoạt động
model Session {
  id             String   @id @default(cuid())
  userId         String
  deviceId       String
  deviceName     String?
  ipAddress      String
  userAgent      String?
  fingerprint    String? // Device fingerprint
  isActive       Boolean  @default(true)
  expiresAt      DateTime
  createdAt      DateTime @default(now())
  lastActivityAt DateTime @default(now())

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

  @@index([userId])
  @@index([deviceId])
  @@index([expiresAt])
  @@index([isActive])
  @@map("sessions")
}

// EN: RefreshToken model - Long-lived refresh tokens
// VI: Model RefreshToken - Refresh token sống lâu
model RefreshToken {
  id        String    @id @default(cuid())
  userId    String
  token     String    @unique
  family    String? // Token family for rotation
  deviceId  String?
  ipAddress String?
  userAgent String?
  expiresAt DateTime
  revokedAt DateTime?
  createdAt DateTime  @default(now())

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

  @@index([userId])
  @@index([token])
  @@index([family])
  @@index([expiresAt])
  @@map("refresh_tokens")
}

// EN: SocialAccount model - Social login accounts
// VI: Model SocialAccount - Tài khoản đăng nhập mạng xã hội
model SocialAccount {
  id           String    @id @default(cuid())
  userId       String
  provider     Provider // GOOGLE, FACEBOOK, GITHUB, APPLE
  providerId   String // ID from provider
  email        String?
  name         String?
  avatar       String?
  accessToken  String?   @db.Text // Encrypted access token
  refreshToken String?   @db.Text // Encrypted refresh token
  expiresAt    DateTime?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt

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

  @@unique([provider, providerId])
  @@index([userId])
  @@index([provider])
  @@map("social_accounts")
}

enum Provider {
  GOOGLE
  FACEBOOK
  GITHUB
  APPLE
  MICROSOFT
}

// EN: MFADevice model - Multi-factor authentication devices
// VI: Model MFADevice - Thiết bị xác thực đa yếu tố
model MFADevice {
  id           String    @id @default(cuid())
  userId       String
  type         MFAType // TOTP, WEBAUTHN
  name         String // Device name
  secret       String? // Encrypted TOTP secret
  credentialId String? // For WebAuthn
  publicKey    String?   @db.Text // For WebAuthn
  counter      Int? // For WebAuthn
  isActive     Boolean   @default(true)
  lastUsedAt   DateTime?
  createdAt    DateTime  @default(now())

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

  @@index([userId])
  @@index([credentialId])
  @@map("mfa_devices")
}

enum MFAType {
  TOTP
  WEBAUTHN
}

// EN: AuthEvent model - Event sourcing for audit logs
// VI: Model AuthEvent - Event sourcing cho audit logs
model AuthEvent {
  id           String   @id @default(cuid())
  userId       String?
  eventType    String // LOGIN, LOGOUT, MFA_ENABLED, PERMISSION_CHANGED, etc.
  eventData    Json
  ipAddress    String?
  userAgent    String?
  success      Boolean  @default(true)
  errorMessage String?  @db.Text
  timestamp    DateTime @default(now())

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

  @@index([userId, timestamp])
  @@index([eventType, timestamp])
  @@index([timestamp])
  @@map("auth_events")
}

// EN: Feature model - Feature flags and toggles
// VI: Model Feature - Feature flags và toggles
model Feature {
  id          String   @id @default(cuid())
  name        String   @unique // Feature identifier
  title       String? // Human-readable title
  description String?  @db.Text // Feature description
  config      Json? // Feature configuration
  enabled     Boolean  @default(true) // Feature toggle
  version     String   @default("1.0.0") // Feature version
  tags        Json? // Feature tags for categorization
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@index([name])
  @@index([enabled])
  @@map("features")
}

// EN: Policy model - ABAC policies
// VI: Model Policy - Chính sách ABAC
model Policy {
  id             String        @id @default(cuid())
  name           String        @unique
  description    String?
  resource       String // Resource this policy applies to
  condition      Json // Policy condition (JSON logic)
  effect         String // ALLOW, DENY
  priority       Int           @default(0) // Higher priority evaluated first
  isActive       Boolean       @default(true)
  organizationId String?
  organization   Organization? @relation(fields: [organizationId], references: [id])
  createdAt      DateTime      @default(now())
  updatedAt      DateTime      @updatedAt

  @@index([resource])
  @@index([isActive, priority])
  @@index([organizationId])
  @@map("policies")
}

// =============================================================================
// EN: Identity Management Models
// VI: Models Quản Lý Danh Tính
// =============================================================================

// EN: Organization model - Multi-tenant organization support
// VI: Model Organization - Hỗ trợ tổ chức multi-tenant
model Organization {
  id        String   @id @default(cuid())
  name      String
  domain    String?  @unique
  parentId  String?
  settings  Json?
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  users    User[]
  groups   Group[]
  policies Policy[]
  parent   Organization?  @relation("OrganizationHierarchy", fields: [parentId], references: [id])
  children Organization[] @relation("OrganizationHierarchy")

  @@index([domain])
  @@map("organizations")
}

// EN: Group model - Groups within organizations
// VI: Model Group - Nhóm trong tổ chức
model Group {
  id             String   @id @default(cuid())
  name           String
  organizationId String?
  description    String?
  isActive       Boolean  @default(true)
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt

  organization Organization?     @relation(fields: [organizationId], references: [id])
  members      GroupMember[]
  permissions  GroupPermission[]

  @@unique([organizationId, name])
  @@index([organizationId])
  @@map("groups")
}

// EN: GroupMember model - Members of a group
// VI: Model GroupMember - Thành viên của nhóm
model GroupMember {
  id        String    @id @default(cuid())
  userId    String
  groupId   String
  role      String    @default("member") // member, admin
  joinedAt  DateTime  @default(now())
  expiresAt DateTime?

  user  User  @relation(fields: [userId], references: [id], onDelete: Cascade)
  group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)

  @@unique([userId, groupId])
  @@index([userId])
  @@index([groupId])
  @@map("group_members")
}

// EN: GroupPermission model - Permissions assigned to groups
// VI: Model GroupPermission - Quyền được gán cho nhóm
model GroupPermission {
  id           String   @id @default(cuid())
  groupId      String
  permissionId String
  createdAt    DateTime @default(now())

  group      Group      @relation(fields: [groupId], references: [id], onDelete: Cascade)
  permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)

  @@unique([groupId, permissionId])
  @@index([groupId])
  @@map("group_permissions")
}

// EN: UserProfile model - Extended user profile information
// VI: Model UserProfile - Thông tin profile mở rộng của user
model UserProfile {
  id            String   @id @default(cuid())
  userId        String   @unique
  firstName     String?
  lastName      String?
  phone         String?
  phoneVerified Boolean  @default(false)
  avatarUrl     String?
  customFields  Json? // Extended attributes
  preferences   Json? // User preferences
  metadata      Json? // Additional metadata
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

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

  @@index([phone])
  @@map("user_profiles")
}

// EN: IdentityVerification model - Identity verification records
// VI: Model IdentityVerification - Hồ sơ xác thực danh tính
model IdentityVerification {
  id         String             @id @default(cuid())
  userId     String
  type       VerificationType
  status     VerificationStatus @default(PENDING)
  method     String?
  token      String?            @unique // OTP token, verification code
  verifiedAt DateTime?
  expiresAt  DateTime?
  metadata   Json? // Verification details
  createdAt  DateTime           @default(now())

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

  @@index([userId, type])
  @@index([token])
  @@index([status])
  @@map("identity_verifications")
}

enum VerificationType {
  EMAIL
  PHONE
  DOCUMENT
  BIOMETRIC
}

enum VerificationStatus {
  PENDING
  VERIFIED
  REJECTED
  EXPIRED
}

// =============================================================================
// EN: Access Management Models
// VI: Models Quản Lý Truy Cập
// =============================================================================

// EN: AccessRequest model - Access requests and approvals
// VI: Model AccessRequest - Yêu cầu và phê duyệt truy cập
model AccessRequest {
  id          String        @id @default(cuid())
  userId      String
  resource    String
  action      String
  reason      String?
  status      RequestStatus @default(PENDING)
  requestedAt DateTime      @default(now())
  reviewedAt  DateTime?
  reviewedBy  String?
  expiresAt   DateTime?
  metadata    Json?

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

  @@index([userId])
  @@index([status])
  @@index([resource])
  @@map("access_requests")
}

enum RequestStatus {
  PENDING
  APPROVED
  REJECTED
  EXPIRED
  CANCELLED
}

// EN: AccessRequestApprover model - Approvers for access requests
// VI: Model AccessRequestApprover - Người phê duyệt yêu cầu truy cập
model AccessRequestApprover {
  id         String         @id @default(cuid())
  requestId  String
  approverId String
  status     ApprovalStatus @default(PENDING)
  comments   String?
  reviewedAt DateTime?

  request AccessRequest @relation(fields: [requestId], references: [id], onDelete: Cascade)

  @@unique([requestId, approverId])
  @@index([approverId])
  @@map("access_request_approvers")
}

enum ApprovalStatus {
  PENDING
  APPROVED
  REJECTED
}

// EN: AccessReview model - Periodic access reviews
// VI: Model AccessReview - Đánh giá truy cập định kỳ
model AccessReview {
  id          String       @id @default(cuid())
  name        String
  description String?
  type        ReviewType
  status      ReviewStatus @default(DRAFT)
  startDate   DateTime
  endDate     DateTime
  createdBy   String
  createdAt   DateTime     @default(now())
  completedAt DateTime?

  items AccessReviewItem[]

  @@index([status])
  @@index([type])
  @@map("access_reviews")
}

enum ReviewType {
  PERIODIC
  ADHOC
  CERTIFICATION
}

enum ReviewStatus {
  DRAFT
  ACTIVE
  COMPLETED
  CANCELLED
}

// EN: AccessReviewItem model - Individual items in an access review
// VI: Model AccessReviewItem - Item riêng lẻ trong đánh giá truy cập
model AccessReviewItem {
  id         String           @id @default(cuid())
  reviewId   String
  userId     String
  resource   String
  access     Json // Current access details
  status     ReviewItemStatus @default(PENDING)
  reviewedBy String?
  reviewedAt DateTime?
  comments   String?

  review AccessReview @relation(fields: [reviewId], references: [id], onDelete: Cascade)

  @@index([reviewId])
  @@index([userId])
  @@index([status])
  @@map("access_review_items")
}

enum ReviewItemStatus {
  PENDING
  APPROVED
  REVOKED
  NO_CHANGE
}

// =============================================================================
// EN: Governance Models
// VI: Models Quản Trị
// =============================================================================

// EN: ComplianceReport model - Compliance reporting
// VI: Model ComplianceReport - Báo cáo tuân thủ
model ComplianceReport {
  id          String         @id @default(cuid())
  type        ComplianceType
  name        String
  periodStart DateTime
  periodEnd   DateTime
  status      ReportStatus   @default(DRAFT)
  data        Json?
  generatedAt DateTime?
  generatedBy String?
  createdAt   DateTime       @default(now())
  updatedAt   DateTime       @updatedAt

  @@index([type])
  @@index([status])
  @@map("compliance_reports")
}

enum ComplianceType {
  GDPR
  SOC2
  ISO27001
  HIPAA
  CUSTOM
}

enum ReportStatus {
  DRAFT
  GENERATED
  PUBLISHED
  ARCHIVED
}

// EN: PolicyTemplate model - Policy templates for governance
// VI: Model PolicyTemplate - Template cho policies trong quản trị
model PolicyTemplate {
  id          String         @id @default(cuid())
  name        String
  category    PolicyCategory
  description String?
  content     Json // Policy template structure
  version     String         @default("1.0.0")
  isActive    Boolean        @default(true)
  createdAt   DateTime       @default(now())
  updatedAt   DateTime       @updatedAt

  @@index([category])
  @@index([isActive])
  @@map("policy_templates")
}

enum PolicyCategory {
  SECURITY
  ACCESS
  COMPLIANCE
  DATA
  PRIVACY
}

// EN: RiskScore model - User risk scoring
// VI: Model RiskScore - Điểm rủi ro của user
model RiskScore {
  id           String    @id @default(cuid())
  userId       String
  score        Int // 0-100
  level        RiskLevel
  factors      Json // Risk factors
  calculatedAt DateTime  @default(now())

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

  @@index([userId])
  @@index([score])
  @@index([level])
  @@map("risk_scores")
}

enum RiskLevel {
  LOW
  MEDIUM
  HIGH
  CRITICAL
}
