generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["postgresqlExtensions"]
}

datasource db {
  provider   = "postgresql"
  url        = env("DATABASE_URL")
  extensions = [pgcrypto, uuid_ossp(map: "uuid-ossp", schema: "public")]
  schemas    = ["admin", "public"]
}

// ─── admin schema (shared with gscAdmin) ───────────────────────

model User {
  id            String        @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  gscsid        String        @unique @db.VarChar(64)
  firstName     String?       @map("first_name") @db.VarChar(128)
  lastName      String?       @map("last_name") @db.VarChar(128)
  displayName   String?       @map("display_name") @db.VarChar(256)
  email         String?       @db.VarChar(256)
  phone         String?       @db.VarChar(32)
  mobile        String?       @db.VarChar(32)
  avatarUrl     String?       @map("avatar_url") @db.VarChar(512)
  timezone      String?       @default("UTC") @db.VarChar(64)
  locale        String?       @default("en") @db.VarChar(10)
  status        String?       @default("active") @db.VarChar(32)
  lastLoginAt   DateTime?     @map("last_login_at") @db.Timestamptz(6)
  lastActivityAt DateTime?    @map("last_activity_at") @db.Timestamptz(6)
  metadata      Json?         @default("{}")
  createdAt     DateTime?     @default(now()) @map("created_at") @db.Timestamptz(6)
  updatedAt     DateTime?     @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
  settings      UserSetting[]

  @@index([gscsid], map: "idx_users_gscsid")
  @@map("users")
  @@schema("admin")
}

model SettingsDefinition {
  id                      String            @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  category                String            @db.VarChar(64)
  key                     String            @db.VarChar(128)
  dataType                String            @map("data_type") @db.VarChar(32)
  defaultValue            Json?             @map("default_value")
  min_value               Decimal?          @db.Decimal
  max_value               Decimal?          @db.Decimal
  allowed_values          Json?
  allow_customer_override Boolean?          @default(true)
  allow_tenant_override   Boolean?          @default(true)
  allow_user_override     Boolean?          @default(true)
  description             String?
  display_order           Int?              @default(0)
  customerSettings        CustomerSetting[]
  tenantSettings          TenantSetting[]
  userSettings            UserSetting[]

  @@unique([category, key])
  @@map("settings_definitions")
  @@schema("admin")
}

model CustomerSetting {
  customerId            String             @map("customer_id") @db.Uuid
  settingId             String             @map("setting_id") @db.Uuid
  value                 Json
  is_mandatory          Boolean?           @default(false)
  allow_tenant_override Boolean?           @default(true)
  updated_by            String?            @db.Uuid
  updatedAt             DateTime?          @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
  setting               SettingsDefinition @relation(fields: [settingId], references: [id], onDelete: Cascade, onUpdate: NoAction)

  @@id([customerId, settingId])
  @@index([settingId, customerId], map: "idx_customer_settings_lookup")
  @@map("customer_settings")
  @@schema("admin")
}

model TenantSetting {
  tenantId            String             @map("tenant_id") @db.Uuid
  settingId           String             @map("setting_id") @db.Uuid
  value               Json
  is_mandatory        Boolean?           @default(false)
  allow_user_override Boolean?           @default(true)
  updated_by          String?            @db.Uuid
  updatedAt           DateTime?          @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
  setting             SettingsDefinition @relation(fields: [settingId], references: [id], onDelete: Cascade, onUpdate: NoAction)

  @@id([tenantId, settingId])
  @@index([settingId, tenantId], map: "idx_tenant_settings_lookup")
  @@map("tenant_settings")
  @@schema("admin")
}

model UserSetting {
  userId    String             @map("user_id") @db.Uuid
  settingId String             @map("setting_id") @db.Uuid
  value     Json
  updatedAt DateTime?          @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
  setting   SettingsDefinition @relation(fields: [settingId], references: [id], onDelete: Cascade, onUpdate: NoAction)
  user      User               @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)

  @@id([userId, settingId])
  @@map("user_settings")
  @@schema("admin")
}

// ─── public schema ─────────────────────────────────────────────

model UserActivityLog {
  id        String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  userId    String   @map("user_id") @db.Uuid
  tenantId  String   @map("tenant_id") @db.Uuid
  action    String   @db.VarChar(64)
  target    String?  @db.VarChar(256)
  metadata  Json?    @default("{}")
  ipAddress String?  @map("ip_address") @db.VarChar(45)
  userAgent String?  @map("user_agent") @db.VarChar(512)
  createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)

  @@index([userId, createdAt(sort: Desc)], map: "idx_user_activity_user")
  @@index([tenantId, createdAt(sort: Desc)], map: "idx_user_activity_tenant")
  @@map("user_activity_log")
  @@schema("public")
}

// ============================================================================
// Privileged Access Management (JIT elevation) — shared with gscAdmin.
// Tables created by gscAdmin's `20260518_pam_init` migration; gscMy
// only needs the model definitions to write/read them.
// See gscAdmin/docs/pam-plan.md for the full design.
// ============================================================================

model PrivilegePolicy {
  roleName              String   @id @map("role_name") @db.VarChar(128)
  maxDurationHours      Int      @default(4) @map("max_duration_hours") @db.SmallInt
  defaultDurationHours  Int      @default(1) @map("default_duration_hours") @db.SmallInt
  approvalMode          String   @default("audit") @map("approval_mode") @db.VarChar(16)
  approverEmail         String?  @map("approver_email") @db.VarChar(256)
  requiresMfa           Boolean  @default(false) @map("requires_mfa")
  eligibleGroup         String   @map("eligible_group") @db.VarChar(128)
  description           String?
  createdAt             DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
  updatedAt             DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
  grants                PrivilegeGrant[]

  @@map("privilege_policies")
  @@schema("admin")
}

model PrivilegeGrant {
  id             String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  gscsid         String   @db.VarChar(64)
  roleName       String   @map("role_name") @db.VarChar(128)
  status         String   @default("pending") @db.VarChar(16)
  approvalToken  String?  @unique @map("approval_token") @db.VarChar(64)
  requestedAt    DateTime @default(now()) @map("requested_at") @db.Timestamptz(6)
  grantedAt      DateTime? @map("granted_at") @db.Timestamptz(6)
  expiresAt      DateTime @map("expires_at") @db.Timestamptz(6)
  grantedBy      String?  @map("granted_by") @db.VarChar(256)
  justification  String
  mfaEvidence    Json?    @map("mfa_evidence")
  revokedAt      DateTime? @map("revoked_at") @db.Timestamptz(6)
  revokedBy      String?  @map("revoked_by") @db.VarChar(64)
  revokeReason   String?  @map("revoke_reason")
  policy         PrivilegePolicy @relation(fields: [roleName], references: [roleName], onUpdate: Cascade)

  @@index([gscsid, roleName], map: "idx_priv_grants_active")
  @@index([expiresAt], map: "idx_priv_grants_expires")
  @@map("privilege_grants")
  @@schema("admin")
}

model PrivilegeAudit {
  id          BigInt   @id @default(autoincrement())
  ts          DateTime @default(now()) @db.Timestamptz(6)
  event       String   @db.VarChar(32)
  gscsid      String   @db.VarChar(64)
  roleName    String   @map("role_name") @db.VarChar(128)
  grantId     String?  @map("grant_id") @db.Uuid
  actorGscsid String?  @map("actor_gscsid") @db.VarChar(64)
  actorEmail  String?  @map("actor_email") @db.VarChar(256)
  detail      Json?

  @@index([gscsid, ts(sort: Desc)], map: "idx_priv_audit_user_ts")
  @@map("privilege_audit")
  @@schema("admin")
}
