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

datasource db {
  provider   = "postgresql"
  url        = env("DATABASE_URL")
  schemas    = ["passenger"]
}

enum UserRole {
  PASSENGER
  AGENT
  SUPERVISOR
  ADMIN
  STAFF

  @@schema("passenger")
}

enum TripStatus {
  SCHEDULED
  BOARDING
  EN_ROUTE
  ARRIVED
  CANCELLED
  DELAYED

  @@schema("passenger")
}

enum SeatKind {
  STANDARD
  PREMIUM
  ACCESSIBLE

  @@schema("passenger")
}

enum SeatStatus {
  AVAILABLE
  HELD
  BOOKED
  BLOCKED

  @@schema("passenger")
}

enum PassengerCategory {
  ADULT
  CHILD

  @@schema("passenger")
}

enum IdDocumentType {
  NATIONAL_ID
  PASSPORT
  DRIVING_LICENSE
  OTHER

  @@schema("passenger")
}

enum Currency {
  ETB
  DJF
  USD

  @@schema("passenger")
}

model CoachType {
  id          String   @id @default(uuid())
  code        String
  name        String
  type        String   @default("passenger") // 'passenger', 'sleeper', 'dining', 'baggage'
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  coaches     Coach[]
  seatClasses SeatClass[]

  @@schema("passenger")
}

model SeatClass {
  id          String   @id @default(uuid())
  coachTypeId String
  name        String
  description String?
  baseFareMinor Int
  isActive    Boolean  @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  coachType   CoachType @relation(fields: [coachTypeId], references: [id])
  fareRules   FareRule[]
  routeFareRules RouteFareRule[]
  segmentFares SegmentFareRule[]
  @@unique([coachTypeId, name])
  @@index([coachTypeId])

  @@schema("passenger")
}

enum BookingStatus {
  DRAFT
  PENDING_PAYMENT
  CONFIRMED
  CANCELLED
  COMPLETED
  NO_SHOW
  REFUNDED

  @@schema("passenger")
}

enum PaymentRegion {
  ETHIOPIA
  DJIBOUTI
  INTERNATIONAL
  GLOBAL

  @@schema("passenger")
}

enum PaymentMethodType {
  TELEBIRR
  CBE_BIRR
  EBIRR
  CARD
  WALLET
  WAAFI

  @@schema("passenger")
}

enum PaymentIntentStatus {
  REQUIRES_ACTION
  PROCESSING
  SUCCEEDED
  FAILED
  CANCELLED
  REFUNDED

  @@schema("passenger")
}

enum WalletLedgerType {
  CREDIT
  DEBIT

  @@schema("passenger")
}

enum NotificationCategory {
  BOOKING
  PAYMENT
  DISRUPTION
  PROMOTION
  SYSTEM

  @@schema("passenger")
}

enum StopStatus {
  COMPLETED
  APPROACHING
  CURRENT
  UPCOMING

  @@schema("passenger")
}

enum SupportConversationStatus {
  OPEN
  RESOLVED
  CLOSED

  @@schema("passenger")
}

enum SupportSender {
  USER
  BOT
  AGENT

  @@schema("passenger")
}

enum LoyaltyTier {
  BRONZE
  SILVER
  GOLD
  PLATINUM

  @@schema("passenger")
}

enum LoyaltyLedgerReason {
  TRIP_COMPLETED
  REWARD_REDEEMED
  PROMO_BONUS
  MANUAL_ADJUSTMENT
  EXPIRY

  @@schema("passenger")
}

enum FoodOrderStatus {
  PENDING
  PREPARING
  READY
  DELIVERED
  CANCELLED

  @@schema("passenger")
}

enum DevicePlatform {
  IOS
  ANDROID
  WEB

  @@schema("passenger")
}

model User {
  id           String    @id @default(uuid())
  email        String    @unique
  phone        String    @unique
  fullName     String
  passwordHash String
  role         UserRole  @default(PASSENGER)
  nationality  String?
  nationalityCode String?
  passportNumber String?
  nationalId   String?
  failedLoginAttempts Int @default(0)
  lockedUntil  DateTime?
  blockedUntil DateTime?
  lastLoginAt  DateTime?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt

  faydaVerified    Boolean   @default(false)
  faydaVerifiedAt  DateTime?
  faydaSub         String?   @unique

  passenger    Passenger?
  agent        Agent?
  sessions     Session[]
  devices      Device[]
  preferences  UserPreferences?
  auditLogs    AuditLog[]
  fraudAlerts  FraudAlert[]

  faydaVerificationSessions FaydaVerificationSession[]

  @@schema("passenger")
}

model Session {
  id        String   @id @default(uuid())
  userId    String
  token     String   @unique
  expiresAt DateTime
  ipAddress String?
  userAgent String?
  lastActivityAt DateTime @default(now())
  createdAt DateTime @default(now())
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@schema("passenger")
}

model Passenger {
  id        String   @id @default(uuid())
  userId    String   @unique
  defaultTravelerProfileId String?
  preferredLanguage String?
  createdAt DateTime @default(now())
  user             User              @relation(fields: [userId], references: [id])
  bookings         Booking[]
  loyalty          LoyaltyAccount?
  wallet           WalletAccount?
  notifications    Notification[]
  travelerProfiles TravelerProfile[]
  savedRoutes      SavedRoute[]
  @@index([userId])

  @@schema("passenger")
}

model TravelerProfile {
  id           String    @id @default(uuid())
  passengerId  String
  fullName     String
  relationship String
  dateOfBirth  DateTime?
  nationalId   String?
  notes        String?
  createdAt    DateTime  @default(now())
  passenger    Passenger @relation(fields: [passengerId], references: [id])

  @@schema("passenger")
}

model Station {
  id       String  @id @default(uuid())
  code     String  @unique
  name     String
  city     String
  countryCode String?
  isOperational Boolean @default(true)
  timezone String  @default("Africa/Addis_Ababa")
  lat      Decimal @db.Decimal(9, 6)
  lng      Decimal @db.Decimal(9, 6)
  originSchedules      TrainSchedule[] @relation("OriginTrips")
  destinationSchedules TrainSchedule[] @relation("DestinationTrips")
  stopTimes            TripStopTime[]
  crowdSignals         StationCrowdSignal[]
  @@index([city, countryCode])

  @@schema("passenger")
}

model Train {
  id           String          @id @default(uuid())
  number       String          @unique
  name         String
  operatorId   String          @default("op_edr")
  operatorName String?
  description  String?
  isActive     Boolean         @default(true)
  createdAt    DateTime        @default(now())
  updatedAt    DateTime        @updatedAt
  schedules    TrainSchedule[]

  @@schema("passenger")
}

model TrainSchedule {
  id                   String            @id @default(uuid())
  trainId              String
  routeId              String?
  originStationId      String
  destinationStationId String
  departureAt          DateTime
  arrivalAt            DateTime
  durationMinutes      Int
  status               TripStatus        @default(SCHEDULED)
  stopsCount           Int               @default(0)
  reservedCount        Int               @default(0)
  onTimePercent        Int               @default(100)
  carbonRating         String            @default("A")
  notes                String?
  train              Train             @relation(fields: [trainId], references: [id])
  route              Route?            @relation(fields: [routeId], references: [id])
  originStation      Station           @relation("OriginTrips", fields: [originStationId], references: [id])
  destinationStation Station           @relation("DestinationTrips", fields: [destinationStationId], references: [id])
  coachAssignments   CoachAssignment[]
  bookings           Booking[]
  stopTimes          TripStopTime[]
  liveStatus         TripLiveStatus?
  menuItems          MenuItem[]
  journeySegments    JourneySegment[]
  @@index([departureAt, originStationId])

  @@schema("passenger")
}

model TripStopTime {
  id                 String        @id @default(uuid())
  scheduleId         String
  stationId          String
  sequence           Int
  plannedArrivalAt   DateTime?
  plannedDepartureAt DateTime?
  actualArrivalAt    DateTime?
  status             StopStatus    @default(UPCOMING)
  schedule TrainSchedule @relation(fields: [scheduleId], references: [id])
  station  Station       @relation(fields: [stationId], references: [id])
  @@unique([scheduleId, sequence])

  @@schema("passenger")
}

model TripLiveStatus {
  id                   String        @id @default(uuid())
  scheduleId           String        @unique
  state                String
  currentLocationLabel String?
  progressPercent      Int           @default(0)
  delayMinutes         Int           @default(0)
  currentSpeedKph      Int?
  platformLabel        String?
  updatedAt            DateTime      @updatedAt
  schedule TrainSchedule @relation(fields: [scheduleId], references: [id])

  @@schema("passenger")
}

model Coach {
  id              String            @id @default(uuid())
  coachTypeId     String
  number          String            @unique
  arrangement     String            @default("2+2") // e.g., '2+2', '3+2', '2+2+2'
  capacity        Int               @default(0) // Total seats/beds
  status          String            @default("ACTIVE") // 'ACTIVE', 'MAINTENANCE', 'INACTIVE'
  createdAt       DateTime          @default(now())
  updatedAt       DateTime          @updatedAt
  coachType   CoachType         @relation(fields: [coachTypeId], references: [id])
  seats       Seat[]
  assignments CoachAssignment[]
  @@index([coachTypeId])

  @@schema("passenger")
}

model CoachAssignment {
  id               String        @id @default(uuid())
  scheduleId       String
  coachId          String
  positionNumber   Int
  isOperational    Boolean       @default(true)
  createdAt        DateTime      @default(now())
  schedule TrainSchedule @relation(fields: [scheduleId], references: [id])
  coach    Coach         @relation(fields: [coachId], references: [id])
  @@unique([scheduleId, positionNumber])
  @@index([scheduleId])

  @@schema("passenger")
}

model Seat {
  id              String     @id @default(uuid())
  coachId         String
  seatNumber      String     // Auto-generated: e.g., '1', '2', '3' (unique per coach)
  row             Int
  col             String
  kind            SeatKind   @default(STANDARD)
  status          SeatStatus @default(AVAILABLE)
  heldUntil       DateTime?
  isWindow        Boolean    @default(false)
  isAisle         Boolean    @default(false)
  bedPosition     String?    // 'lower', 'middle', 'upper'
  premiumFeeMinor Int        @default(0)
  coach        Coach         @relation(fields: [coachId], references: [id])
  bookingSeats BookingSeat[]
  blocks       SeatBlock[]
  ticketSeats  TicketSeat[]
  @@unique([coachId, seatNumber])
  @@unique([coachId, row, col])
  @@index([coachId])

  @@schema("passenger")
}

model SeatHold {
  id          String   @id @default(uuid())
  scheduleId  String
  seatIds     String[]
  fareQuoteId String?
  passengerId String
  createdBy   String?
  expiresAt   DateTime
  createdAt   DateTime @default(now())
  @@index([expiresAt])

  @@schema("passenger")
}

model FareRule {
  id            String    @id @default(uuid())
  tripId        String?
  route         String?
  nationality   String?   // Ethiopian, Djiboutian, Other
  seatClassId   String
  baseFareMinor Int
  seatClass SeatClass @relation(fields: [seatClassId], references: [id])
  currency      String       @default("ETB")
  refundable    Boolean      @default(true)
  validFrom     DateTime
  validUntil    DateTime?
  createdAt     DateTime     @default(now())

  @@schema("passenger")
}

model Booking {
  id               String        @id @default(uuid())
  bookingRef       String        @unique
  passengerId      String
  scheduleId       String
  status           BookingStatus @default(DRAFT)
  currency         String        @default("ETB")
  totalMinor       Int
  adultCount       Int           @default(1)
  childCount       Int           @default(0)
  displayCurrency  Currency?
  displayTotalMinor Int?
  bookingType      String        @default("ONE_WAY")
  contactEmail     String?
  contactPhone     String?
  userAgent        String?
  source           String        @default("WEB")
  promoCode        String?
  paidAt           DateTime?
  createdAt        DateTime      @default(now())
  updatedAt        DateTime      @updatedAt
  passenger     Passenger      @relation(fields: [passengerId], references: [id])
  schedule      TrainSchedule  @relation(fields: [scheduleId], references: [id])
  seats         BookingSeat[]
  paymentIntent PaymentIntent?
  ticket        Ticket?
  foodOrders    FoodOrder[]
  agentBooking  AgentBooking?
  modifications BookingModification[]
  cancellation  BookingCancellation?
  baggage       BaggageBooking[]
  @@index([passengerId, status])

  @@schema("passenger")
}

model BookingSeat {
  id                  String            @id @default(uuid())
  bookingId           String
  seatId              String
  passengerName       String
  dateOfBirth         DateTime?
  passengerCategory   PassengerCategory @default(ADULT)
  idDocumentType      IdDocumentType?
  idDocumentNumber    String?
  passportNumber      String?
  passportCountry     String?
  verifaydaVerified   Boolean           @default(false)
  verifaydaData       Json?
  faydaVerifiedAt     DateTime?
  faydaSub            String?
  faydaVerifiedName   String?
  seatLabelSnapshot   String?
  fareMinor           Int?
  displayCurrency     Currency?
  displayFareMinor    Int?
  booking Booking @relation(fields: [bookingId], references: [id])
  seat    Seat    @relation(fields: [seatId], references: [id])

  @@schema("passenger")
}

model PaymentMethod {
  id          String            @id @default(uuid())
  type        PaymentMethodType @unique
  displayName String
  region      PaymentRegion     @default(GLOBAL)
  currency    String            @default("ETB")
  providerId  String?
  isDefault   Boolean           @default(false)
  enabled     Boolean           @default(true)
  sortOrder   Int               @default(0)
  createdAt   DateTime          @default(now())
  updatedAt   DateTime          @updatedAt

  @@schema("passenger")
}

model PaymentIntent {
  id              String              @id @default(uuid())
  bookingId       String              @unique
  amountMinor     Int
  currency        String              @default("ETB")
  method          PaymentMethodType
  provider        String?
  status          PaymentIntentStatus @default(REQUIRES_ACTION)
  providerRef     String?
  clientAction    Json?
  merchantOrderId String?             @unique
  providerOrderId String?
  providerTxnId   String?
  rawInitiation   Json?
  paidAt          DateTime?
  refundedAt      DateTime?
  captureMethod   String?
  failureCode     String?
  failureMessage  String?
  expiresAt       DateTime?
  createdAt       DateTime            @default(now())
  updatedAt       DateTime            @updatedAt
  booking Booking         @relation(fields: [bookingId], references: [id])
  refunds PaymentRefund[]
  @@index([providerOrderId])
  @@index([providerTxnId])

  @@schema("passenger")
}

model PaymentWebhookEvent {
  id              String            @id @default(uuid())
  provider        PaymentMethodType
  externalEventId String
  merchantOrderId String?
  providerTxnId   String?
  signatureValid  Boolean
  status          String
  payload         Json
  receivedAt      DateTime          @default(now())
  processedAt     DateTime?
  processingError String?
  @@unique([provider, externalEventId])
  @@index([merchantOrderId])

  @@schema("passenger")
}

model PaymentRefund {
  id               String   @id @default(uuid())
  paymentIntentId  String
  amountMinor      Int
  reason           String?
  providerRefundId String?
  status           String
  createdAt        DateTime @default(now())
  paymentIntent PaymentIntent @relation(fields: [paymentIntentId], references: [id])

  @@schema("passenger")
}

model Ticket {
  id          String    @id @default(uuid())
  bookingId   String    @unique
  bookingRef  String
  status      String    @default("CONFIRMED")
  qrPayload   String
  barcodePayload String?
  pdfUrl      String?
  deliveryChannel String @default("EMAIL")
  issuedAt    DateTime  @default(now())
  validatedAt DateTime?
  validatorId String?
  booking Booking @relation(fields: [bookingId], references: [id])
  validationLogs GateValidationLog[]
  seats TicketSeat[]

  @@schema("passenger")
}

model TicketSeat {
  id        String   @id @default(uuid())
  ticketId  String
  seatId    String
  seatIndex Int      @default(0)
  ticket    Ticket   @relation(fields: [ticketId], references: [id], onDelete: Cascade)
  seat      Seat     @relation(fields: [seatId], references: [id])
  @@index([ticketId])
  @@index([seatId])

  @@schema("passenger")
}

model LoyaltyAccount {
  id            String      @id @default(uuid())
  passengerId   String      @unique
  pointsBalance Int         @default(0)
  lifetimePoints Int        @default(0)
  tier          LoyaltyTier @default(BRONZE)
  tierUpdatedAt DateTime?
  updatedAt     DateTime    @updatedAt
  passenger Passenger            @relation(fields: [passengerId], references: [id])
  ledger    LoyaltyLedgerEntry[]
  rewards   LoyaltyReward[]

  @@schema("passenger")
}

model LoyaltyLedgerEntry {
  id           String              @id @default(uuid())
  accountId    String
  delta        Int
  reason       LoyaltyLedgerReason
  bookingId    String?
  balanceAfter Int
  createdAt    DateTime            @default(now())
  account LoyaltyAccount @relation(fields: [accountId], references: [id])

  @@schema("passenger")
}

model LoyaltyReward {
  id          String  @id @default(uuid())
  accountId   String
  title       String
  costPoints  Int
  available   Boolean @default(true)
  description String?
  account LoyaltyAccount @relation(fields: [accountId], references: [id])

  @@schema("passenger")
}

model WalletAccount {
  id           String   @id @default(uuid())
  passengerId  String   @unique
  balanceMinor Int      @default(0)
  status       String   @default("ACTIVE")
  holdMinor    Int      @default(0)
  currency     String   @default("ETB")
  updatedAt    DateTime @updatedAt
  passenger Passenger           @relation(fields: [passengerId], references: [id])
  ledger    WalletLedgerEntry[]
  @@index([passengerId])

  @@schema("passenger")
}

model WalletLedgerEntry {
  id                String           @id @default(uuid())
  walletId          String
  type              WalletLedgerType
  amountMinor       Int
  balanceAfterMinor Int
  description       String
  relatedBookingId  String?
  createdAt         DateTime         @default(now())
  wallet WalletAccount @relation(fields: [walletId], references: [id])

  @@schema("passenger")
}

model Notification {
  id          String               @id @default(uuid())
  passengerId String
  title       String
  body        String
  category    NotificationCategory
  read        Boolean              @default(false)
  deepLink    String?
  metadata    Json?
  createdAt   DateTime             @default(now())
  passenger Passenger @relation(fields: [passengerId], references: [id])

  @@schema("passenger")
}

model Promotion {
  id             String   @id @default(uuid())
  title          String
  subtitle       String?
  code           String   @unique
  percentOff     Int?
  amountOffMinor Int?
  validUntil     DateTime
  ctaLabel       String?
  deepLink       String?
  active         Boolean  @default(true)
  createdAt      DateTime @default(now())

  @@schema("passenger")
}

model StationCrowdSignal {
  id          String   @id @default(uuid())
  stationId   String
  level       String
  label       String
  statusLabel String
  confidence  Int?
  observedAt  DateTime?
  updatedAt   DateTime @updatedAt
  station Station @relation(fields: [stationId], references: [id])

  @@schema("passenger")
}

model WeatherAlert {
  id         String   @id @default(uuid())
  region     String
  severity   String
  title      String
  message    String
  validUntil DateTime
  createdAt  DateTime @default(now())

  @@schema("passenger")
}

model MenuCategory {
  id    String     @id @default(uuid())
  name  String
  items MenuItem[]

  @@schema("passenger")
}

model MenuItem {
  id         String  @id @default(uuid())
  scheduleId String
  categoryId String
  name       String
  priceMinor Int
  currency   String  @default("ETB")
  available  Boolean @default(true)
  availableUntil DateTime?
  schedule TrainSchedule @relation(fields: [scheduleId], references: [id])
  category MenuCategory  @relation(fields: [categoryId], references: [id])

  @@schema("passenger")
}

model FoodOrder {
  id         String          @id @default(uuid())
  bookingId  String
  status     FoodOrderStatus @default(PENDING)
  totalMinor Int
  currency   String          @default("ETB")
  specialInstructions String?
  estimatedReadyAt DateTime?
  createdAt  DateTime        @default(now())
  booking Booking         @relation(fields: [bookingId], references: [id])
  items   FoodOrderItem[]

  @@schema("passenger")
}

model FoodOrderItem {
  id             String @id @default(uuid())
  orderId        String
  menuItemId     String
  name           String
  quantity       Int
  unitPriceMinor Int?
  lineTotalMinor Int
  order FoodOrder @relation(fields: [orderId], references: [id])

  @@schema("passenger")
}

model FaqCategory {
  id       String       @id @default(uuid())
  title    String
  iconKey  String?
  articles FaqArticle[]

  @@schema("passenger")
}

model FaqArticle {
  id             String      @id @default(uuid())
  categoryId     String
  question       String
  answerMarkdown String
  rank           Int         @default(0)
  category FaqCategory @relation(fields: [categoryId], references: [id])

  @@schema("passenger")
}

model SupportConversation {
  id        String                    @id @default(uuid())
  userId    String
  assignedAgentId String?
  status    SupportConversationStatus @default(OPEN)
  createdAt DateTime                  @default(now())
  messages  SupportMessage[]

  @@schema("passenger")
}

model SupportMessage {
  id             String        @id @default(uuid())
  conversationId String
  sender         SupportSender
  text           String
  attachments    Json?
  createdAt      DateTime      @default(now())
  conversation SupportConversation @relation(fields: [conversationId], references: [id])

  @@schema("passenger")
}

model UserPreferences {
  id                     String  @id @default(uuid())
  userId                 String  @unique
  pushEnabled            Boolean @default(true)
  emailEnabled           Boolean @default(true)
  smsEnabled             Boolean @default(false)
  promosEnabled          Boolean @default(true)
  biometricEnabled       Boolean @default(false)
  twoFactorEnabled       Boolean @default(false)
  defaultPaymentMethodId String?
  autoDownloadTickets    Boolean @default(true)
  dataSharing            Boolean @default(false)
  locale                 String  @default("en")
  darkMode               Boolean @default(false)
  language               String  @default("en")
  user User @relation(fields: [userId], references: [id])

  @@schema("passenger")
}

model Device {
  id         String         @id @default(uuid())
  userId     String
  platform   DevicePlatform
  name       String
  pushToken  String?
  trusted    Boolean        @default(false)
  lastSeenAt DateTime       @default(now())
  user User @relation(fields: [userId], references: [id])

  @@schema("passenger")
}

model SavedRoute {
  id            String   @id @default(uuid())
  passengerId   String
  fromStationId String
  toStationId   String
  fromName      String
  toName        String
  tripCount     Int      @default(0)
  createdAt     DateTime @default(now())
  passenger Passenger @relation(fields: [passengerId], references: [id])

  @@schema("passenger")
}

model Journey {
  id         String   @id @default(uuid())
  passengerId String
  status     String
  totalMinor Int
  currency   String   @default("ETB")
  createdAt  DateTime @default(now())
  journeySegments JourneySegment[]

  @@schema("passenger")
}

model JourneySegment {
  id                   String        @id @default(uuid())
  journeyId            String
  scheduleId           String
  segmentOrder         Int
  seatId               String?
  coachId              String?
  departureStationId   String
  arrivalStationId     String
  journey  Journey       @relation(fields: [journeyId], references: [id])
  schedule TrainSchedule @relation(fields: [scheduleId], references: [id])

  @@schema("passenger")
}

model OtpCode {
  id        String   @id @default(uuid())
  userId    String?
  email     String?
  phone     String?
  code      String
  purpose   String
  expiresAt DateTime
  verified  Boolean  @default(false)
  createdAt DateTime @default(now())
  @@index([email, phone])

  @@schema("passenger")
}

model PasswordResetToken {
  id        String   @id @default(uuid())
  userId    String
  token     String   @unique
  expiresAt DateTime
  used      Boolean  @default(false)
  createdAt DateTime @default(now())
  @@index([userId])

  @@schema("passenger")
}

model Route {
  id          String   @id @default(uuid())
  code        String   @unique
  name        String
  description String?
  effectiveFrom DateTime
  effectiveUntil DateTime?
  active      Boolean  @default(true)
  createdAt   DateTime @default(now())
  stops       RouteStop[]
  fareRules   RouteFareRule[]
  segmentFares SegmentFareRule[]
  schedules   TrainSchedule[]

  @@schema("passenger")
}

model RouteStop {
  id          String   @id @default(uuid())
  routeId     String
  stationId   String
  sequence    Int
  distanceKm  Int?
  createdAt   DateTime @default(now())
  route       Route    @relation(fields: [routeId], references: [id], onDelete: Cascade)
  @@unique([routeId, sequence])
  @@index([routeId, stationId])

  @@schema("passenger")
}

model RouteFareRule {
  id                String            @id @default(uuid())
  routeId           String
  seatClassId       String
  passengerCategory PassengerCategory @default(ADULT)
  baseFareMinor     Int
  discountPercent   Int?
  taxPercent        Int?
  surchargeMinor    Int?
  currency          String            @default("ETB")
  validFrom         DateTime
  validUntil        DateTime?
  createdAt         DateTime          @default(now())
  route     Route     @relation(fields: [routeId], references: [id], onDelete: Cascade)
  seatClass SeatClass @relation(fields: [seatClassId], references: [id])
  @@index([routeId, seatClassId])

  @@schema("passenger")
}

model SegmentFareRule {
  id              String    @id @default(uuid())
  routeId         String
  originStopSequence Int
  destinationStopSequence Int
  seatClassId     String
  baseFareMinor   Int
  nationality     String?   // Optional: Ethiopian, Djiboutian, Other
  currency        String    @default("ETB")
  validFrom       DateTime
  validUntil      DateTime?
  createdAt       DateTime  @default(now())
  route           Route     @relation(fields: [routeId], references: [id], onDelete: Cascade)
  seatClass       SeatClass @relation(fields: [seatClassId], references: [id])
  @@unique([routeId, originStopSequence, destinationStopSequence, seatClassId, nationality])
  @@index([routeId, seatClassId])

  @@schema("passenger")
}

model Agent {
  id              String   @id @default(uuid())
  userId          String   @unique
  agentCode       String   @unique
  stationId       String?
  commissionRate  Int      @default(5)
  active          Boolean  @default(true)
  createdAt       DateTime @default(now())
  user            User     @relation(fields: [userId], references: [id])
  bookings        AgentBooking[]
  shifts          AgentShift[]
  commissions     AgentCommission[]

  @@schema("passenger")
}

model AgentBooking {
  id              String        @id @default(uuid())
  agentId         String
  bookingId       String        @unique
  paymentMethod   String
  cashReceived    Int?
  changeGiven     Int?
  paperTicket     Boolean       @default(false)
  createdAt       DateTime      @default(now())
  agent           Agent         @relation(fields: [agentId], references: [id])
  booking         Booking       @relation(fields: [bookingId], references: [id])

  @@schema("passenger")
}

model AgentShift {
  id              String   @id @default(uuid())
  agentId         String
  openedAt        DateTime @default(now())
  closedAt        DateTime?
  openingBalance  Int      @default(0)
  closingBalance  Int?
  reconciled      Boolean  @default(false)
  notes           String?
  agent           Agent    @relation(fields: [agentId], references: [id])
  @@index([agentId, openedAt])

  @@schema("passenger")
}

model AgentCommission {
  id          String   @id @default(uuid())
  agentId     String
  bookingId   String
  amountMinor Int
  rate        Int
  paidAt      DateTime?
  createdAt   DateTime @default(now())
  agent       Agent    @relation(fields: [agentId], references: [id])
  @@index([agentId, paidAt])

  @@schema("passenger")
}

model BookingModification {
  id              String   @id @default(uuid())
  bookingId       String
  modifiedBy      String
  modificationType String
  oldData         Json
  newData         Json
  fareAdjustment  Int      @default(0)
  reason          String?
  createdAt       DateTime @default(now())
  booking         Booking  @relation(fields: [bookingId], references: [id])
  @@index([bookingId])

  @@schema("passenger")
}

model BookingCancellation {
  id              String   @id @default(uuid())
  bookingId       String   @unique
  cancelledBy     String
  reason          String?
  refundAmount    Int
  refundMethod    String
  refundStatus    String
  processedAt     DateTime?
  createdAt       DateTime @default(now())
  booking         Booking  @relation(fields: [bookingId], references: [id])

  @@schema("passenger")
}

model GateValidationLog {
  id          String   @id @default(uuid())
  ticketId    String
  validatorId String
  gateId      String?
  status      String
  reason      String?
  validatedAt DateTime @default(now())
  ticket      Ticket   @relation(fields: [ticketId], references: [id])
  @@index([ticketId])
  @@index([validatorId])

  @@schema("passenger")
}

model BaggageAllowance {
  id              String   @id @default(uuid())
  seatClassId     String
  maxWeightKg     Int
  maxPiecesCount  Int
  excessFeePerKg  Int
  currency        String   @default("ETB")
  createdAt       DateTime @default(now())

  @@schema("passenger")
}

model BaggageBooking {
  id              String   @id @default(uuid())
  bookingId       String
  weightKg        Int
  piecesCount     Int
  excessFeeMinor  Int      @default(0)
  paid            Boolean  @default(false)
  createdAt       DateTime @default(now())
  booking         Booking  @relation(fields: [bookingId], references: [id])
  @@index([bookingId])

  @@schema("passenger")
}

model AuditLog {
  id          String   @id @default(uuid())
  userId      String?
  action      String
  entityType  String
  entityId    String?
  oldData     Json?
  newData     Json?
  ipAddress   String?
  userAgent   String?
  createdAt   DateTime @default(now())
  user        User?    @relation(fields: [userId], references: [id])
  @@index([userId, createdAt])
  @@index([entityType, entityId])

  @@schema("passenger")
}

model NotificationTemplate {
  id          String   @id @default(uuid())
  code        String   @unique
  channel     String
  subject     String?
  bodyTemplate String
  active      Boolean  @default(true)
  createdAt   DateTime @default(now())

  @@schema("passenger")
}

model SeatBlock {
  id          String   @id @default(uuid())
  seatId      String
  reason      String
  blockedBy   String
  approvedBy  String?
  blockedAt   DateTime @default(now())
  unblockAt   DateTime?
  seat        Seat     @relation(fields: [seatId], references: [id])
  @@index([seatId])

  @@schema("passenger")
}

model OperationalReport {
  id          String   @id @default(uuid())
  reportType  String
  dateFrom    DateTime
  dateTo      DateTime
  data        Json
  generatedBy String?
  createdAt   DateTime @default(now())
  @@index([reportType, dateFrom])

  @@schema("passenger")
}

model FraudRule {
  id        String   @id @default(uuid())
  type      String   @unique
  enabled   Boolean  @default(true)
  threshold Float
  config    Json?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@schema("passenger")
}

model FraudAlert {
  id             String   @id @default(uuid())
  userId         String
  eventType      String
  triggeredRules String[]
  context        Json
  severity       String   @default("MEDIUM")
  acknowledged   Boolean  @default(false)
  createdAt      DateTime @default(now())
  user           User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  @@index([userId, createdAt])
  @@index([acknowledged])

  @@schema("passenger")
}

model CurrencyExchangeRate {
  id            String   @id @default(uuid())
  fromCurrency  Currency
  toCurrency    Currency
  rate          Decimal  @db.Decimal(18, 6)
  effectiveDate DateTime @default(now())
  source        String   @default("MANUAL")
  createdAt     DateTime @default(now())
  @@unique([fromCurrency, toCurrency, effectiveDate])
  @@index([fromCurrency, toCurrency])

  @@schema("passenger")
}

model VerifaydaVerification {
  id                String   @id @default(uuid())
  bookingId         String?
  nationalId        String
  requestPayload    Json
  responsePayload   Json?
  verified          Boolean  @default(false)
  failureReason     String?
  verifiedAt        DateTime?
  createdAt         DateTime @default(now())
  @@index([nationalId])
  @@index([bookingId])

  @@schema("passenger")
}

model SavedPassengerProfile {
  id                String         @id @default(uuid())
  userId            String?
  deviceId          String?
  passengerName     String
  dateOfBirth       DateTime
  idDocumentType    IdDocumentType
  passportNumber    String?
  passportCountry   String?
  nationality       String?
  phone             String?
  email             String?
  createdAt         DateTime       @default(now())
  updatedAt         DateTime       @updatedAt
  @@index([userId])
  @@index([deviceId])

  @@schema("passenger")
}

model FaydaVerificationSession {
  id               String    @id @default(uuid())
  state            String    @unique
  codeVerifier     String
  purpose          String    @default("PURCHASE")
  platform         String    @default("WEB") // WEB | MOBILE — recorded for audit
  saveToAccount    Boolean   @default(false)
  status           String    @default("PENDING")
  errorCode        String?
  errorDescription String?
  authCode         String?
  createdAt        DateTime  @default(now())
  expiresAt        DateTime
  completedAt      DateTime?

  userId    String?
  bookingId String?

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

  @@index([userId])
  @@index([bookingId])
  @@index([state])
  @@index([expiresAt])

  @@schema("passenger")
}

