// Prisma Schema for tOS - Team Operating System
// Database: PostgreSQL

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

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

// =============================================================================
// ENUMS
// =============================================================================

enum ContractType {
  FULL_TIME
  PART_TIME
  MINI_JOB
  INTERN
  WORKING_STUDENT
  FREELANCE
  TEMPORARY
}

enum AbsenceType {
  VACATION
  SICK
  SICK_CHILD
  SPECIAL_LEAVE
  UNPAID_LEAVE
  PARENTAL_LEAVE
  HOME_OFFICE
  BUSINESS_TRIP
  TRAINING
  COMPENSATION
}

enum ApprovalStatus {
  PENDING
  APPROVED
  REJECTED
  CANCELLED
}

enum TimeEntryType {
  REGULAR
  OVERTIME
  HOLIDAY
  SICK
  VACATION
  CORRECTION
}

enum ReviewType {
  PROBATION
  ANNUAL
  PROMOTION
  PROJECT
  FEEDBACK
  EXIT
}

enum S3StatusType {
  GREEN
  YELLOW
  RED
  NOT_APPLICABLE
}

enum S3Type {
  SEIRI   // Sort - Aussortieren
  SEITON  // Set in Order - Aufräumen
  SEISO   // Shine - Sauberkeit
}

enum SkillLevel {
  NONE
  BEGINNER
  INTERMEDIATE
  ADVANCED
  EXPERT
  TRAINER
}

enum IntegrationType {
  DATEV
  PERSONIO
  SAP
  CALENDAR
  EMAIL
  CUSTOM
  PLENTYONE
  ZULIP
  TODOIST
  FREESCOUT
  NEXTCLOUD
  ECODMS
  GEMBADOCS
}

enum SyncStatus {
  PENDING
  RUNNING
  SUCCESS
  ERROR
}

// SQCDM Categories for Morning Meeting
enum SQCDMCategory {
  SAFETY    // S - Sicherheit
  QUALITY   // Q - Qualitaet
  COST      // C - Kosten
  DELIVERY  // D - Lieferung
  MORALE    // M - Moral/Mitarbeiter
}

// Meeting Status
enum MeetingStatus {
  SCHEDULED
  IN_PROGRESS
  COMPLETED
  CANCELLED
}

// KPI Status (Traffic Light)
enum KPIStatus {
  GREEN
  YELLOW
  RED
  NEUTRAL
}

// Trend Direction
enum Trend {
  UP
  DOWN
  STABLE
}

// Action Status
enum ActionStatus {
  OPEN
  IN_PROGRESS
  COMPLETED
  CANCELLED
}

// Priority Level
enum Priority {
  LOW
  MEDIUM
  HIGH
  CRITICAL
}

// =============================================================================
// CORE MODELS
// =============================================================================

model User {
  id          String   @id @default(cuid())
  email       String   @unique
  firstName   String
  lastName    String
  keycloakId  String?  @unique
  avatar      String?
  isActive    Boolean  @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  // Relations
  departmentId String?
  department   Department? @relation("UserDepartment", fields: [departmentId], references: [id])
  roles        UserRole[]
  employee     Employee?
  preferences  UserPreference?
  auditLogs    AuditLog[]

  // Manager relations
  managedDepartments Department[]      @relation("DepartmentManager")
  correctedTimeEntries TimeEntry[]     @relation("TimeEntryCorrectedBy")
  approvedAbsences   Absence[]         @relation("AbsenceApprovedBy")
  conductedReviews   EmployeeReview[]  @relation("ReviewConductedBy")
  skillAssessments   SkillMatrixEntry[] @relation("SkillAssessedBy")
  integrationCredentials IntegrationCredential[]

  // LEAN 3S relations
  s3PlansCreated    S3Plan[]          @relation("S3PlanCreatedBy")
  s3StatusCompleted S3Status[]        @relation("S3StatusCompletedBy")

  // Morning Meeting relations
  conductedMeetings      MorningMeeting[]       @relation("MeetingConductor")
  assignedMeetingActions MorningMeetingAction[] @relation("ActionAssignee")

  @@index([email])
  @@index([keycloakId])
  @@index([departmentId])
}

model Department {
  id        String   @id @default(cuid())
  name      String
  code      String?  @unique
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  // Self-relation for hierarchy
  parentId  String?
  parent    Department?  @relation("DepartmentHierarchy", fields: [parentId], references: [id])
  children  Department[] @relation("DepartmentHierarchy")

  // Manager relation
  managerId String?
  manager   User?   @relation("DepartmentManager", fields: [managerId], references: [id])

  // Relations
  users           User[]           @relation("UserDepartment")
  onboardingTasks OnboardingTask[]
  s3Plans         S3Plan[]
  skills          Skill[]
  morningMeetings MorningMeeting[]

  @@index([parentId])
  @@index([managerId])
}

model Role {
  id          String   @id @default(cuid())
  name        String   @unique
  description String?
  permissions Json     @default("[]")
  isSystem    Boolean  @default(false)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  // Relations
  users UserRole[]

  @@index([name])
}

model UserRole {
  id        String   @id @default(cuid())
  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)

  @@unique([userId, roleId])
  @@index([userId])
  @@index([roleId])
}

// =============================================================================
// HR MODELS
// =============================================================================

model Employee {
  id             String       @id @default(cuid())
  employeeNumber String       @unique
  position       String
  entryDate      DateTime
  exitDate       DateTime?
  contractType   ContractType
  workingHours   Float        @default(40)
  salary         String?      // Encrypted salary (AES-256-GCM)
  taxClass       Int?
  bankAccount    Json?        // Encrypted bank account (AES-256-GCM)
  isActive       Boolean      @default(true)
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @updatedAt

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

  timeEntries      TimeEntry[]
  absences         Absence[]
  reviews          EmployeeReview[]
  skillMatrixEntries SkillMatrixEntry[]

  @@index([employeeNumber])
  @@index([userId])
  @@index([entryDate])
}

model TimeEntry {
  id           String        @id @default(cuid())
  date         DateTime      @db.Date
  clockIn      DateTime?
  clockOut     DateTime?
  breakMinutes Int           @default(0)
  type         TimeEntryType @default(REGULAR)
  note         String?
  isLocked     Boolean       @default(false)
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt

  // Relations
  employeeId    String
  employee      Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
  correctedById String?
  correctedBy   User?    @relation("TimeEntryCorrectedBy", fields: [correctedById], references: [id])

  @@unique([employeeId, date])
  @@index([employeeId])
  @@index([date])
  @@index([correctedById])
}

model Absence {
  id        String         @id @default(cuid())
  type      AbsenceType
  startDate DateTime       @db.Date
  endDate   DateTime       @db.Date
  days      Float
  status    ApprovalStatus @default(PENDING)
  note      String?
  createdAt DateTime       @default(now())
  updatedAt DateTime       @updatedAt

  // Relations
  employeeId   String
  employee     Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
  approvedById String?
  approvedBy   User?    @relation("AbsenceApprovedBy", fields: [approvedById], references: [id])

  @@index([employeeId])
  @@index([startDate, endDate])
  @@index([status])
  @@index([approvedById])
}

model EmployeeReview {
  id        String     @id @default(cuid())
  date      DateTime
  type      ReviewType
  notes     String?    @db.Text
  goals     Json?
  rating    Int?
  createdAt DateTime   @default(now())
  updatedAt DateTime   @updatedAt

  // Relations
  employeeId String
  employee   Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
  reviewerId String
  reviewer   User     @relation("ReviewConductedBy", fields: [reviewerId], references: [id])

  @@index([employeeId])
  @@index([reviewerId])
  @@index([date])
  @@index([type])
}

model OnboardingTask {
  id          String  @id @default(cuid())
  title       String
  description String? @db.Text
  dueOffset   Int     @default(0) // Days from entry date
  assignedTo  String? // Role or specific user type
  sortOrder   Int     @default(0)
  isActive    Boolean @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  // Relations
  departmentId String?
  department   Department? @relation(fields: [departmentId], references: [id])

  @@index([departmentId])
  @@index([sortOrder])
}

// =============================================================================
// INTEGRATION MODELS
// =============================================================================

model IntegrationCredential {
  id          String          @id @default(cuid())
  type        IntegrationType
  name        String
  credentials String          // Encrypted JSON (AES-256-GCM)
  isActive    Boolean         @default(true)
  lastUsed    DateTime?
  lastSync    DateTime?
  syncStatus  SyncStatus      @default(PENDING)
  syncError   String?
  createdAt   DateTime        @default(now())
  updatedAt   DateTime        @updatedAt
  createdById String
  createdBy   User            @relation(fields: [createdById], references: [id])

  // Relations
  syncHistory IntegrationSyncHistory[]

  @@unique([type, name])
  @@index([type])
  @@index([isActive])
  @@index([createdById])
}

model IntegrationSyncHistory {
  id            String          @id @default(cuid())
  credentialId  String
  credential    IntegrationCredential @relation(fields: [credentialId], references: [id], onDelete: Cascade)
  status        SyncStatus
  startedAt     DateTime        @default(now())
  completedAt   DateTime?
  duration      Int?            // Duration in milliseconds
  recordsProcessed Int?
  error         String?
  metadata      Json?           // Additional sync metadata
  createdAt     DateTime        @default(now())

  @@index([credentialId])
  @@index([status])
  @@index([startedAt])
}

// =============================================================================
// LEAN MODELS - 3S / 5S
// =============================================================================

model S3Plan {
  id        String   @id @default(cuid())
  year      Int
  month     Int
  isActive  Boolean  @default(true)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  // Relations
  departmentId String
  department   Department   @relation(fields: [departmentId], references: [id])
  createdById  String
  createdBy    User         @relation("S3PlanCreatedBy", fields: [createdById], references: [id])
  categories   S3Category[]

  @@unique([departmentId, year, month])
  @@index([departmentId])
  @@index([year, month])
  @@index([createdById])
}

model S3Category {
  id        String   @id @default(cuid())
  name      String
  s3Type    S3Type   // SEIRI, SEITON, SEISO
  sortOrder Int      @default(0)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  // Relations
  planId   String
  plan     S3Plan     @relation(fields: [planId], references: [id], onDelete: Cascade)
  statuses S3Status[]

  @@index([planId])
  @@index([sortOrder])
  @@index([s3Type])
}

model S3Status {
  id            String       @id @default(cuid())
  week          Int          // 1-53
  status        S3StatusType
  photo         String?      // URL to uploaded image
  note          String?
  completedAt   DateTime?
  createdAt     DateTime     @default(now())
  updatedAt     DateTime     @updatedAt

  // Relations
  categoryId    String
  category      S3Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
  completedById String?
  completedBy   User?      @relation("S3StatusCompletedBy", fields: [completedById], references: [id])

  @@unique([categoryId, week])
  @@index([categoryId])
  @@index([week])
  @@index([status])
  @@index([completedById])
}

// =============================================================================
// LEAN MODELS - Morning Meeting (Shopfloor Management)
// =============================================================================

model MorningMeeting {
  id           String        @id @default(cuid())
  date         DateTime      @db.Date
  startTime    DateTime?     // Actual start time
  endTime      DateTime?     // Actual end time
  duration     Int?          // Duration in minutes (calculated)
  participants Json?         // Array of participant user IDs
  notes        String?       @db.Text
  status       MeetingStatus @default(SCHEDULED)
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt

  // Relations
  departmentId String
  department   Department              @relation(fields: [departmentId], references: [id])
  conductorId  String?
  conductor    User?                   @relation("MeetingConductor", fields: [conductorId], references: [id])
  topics       MorningMeetingTopic[]
  actions      MorningMeetingAction[]

  @@unique([departmentId, date])
  @@index([departmentId])
  @@index([date])
  @@index([status])
  @@index([conductorId])
}

model MorningMeetingTopic {
  id        String        @id @default(cuid())
  category  SQCDMCategory // SAFETY, QUALITY, COST, DELIVERY, MORALE
  title     String
  value     String?       // Current value
  target    String?       // Target value
  unit      String?       // Unit (%, pieces, EUR, etc.)
  status    KPIStatus     @default(NEUTRAL)
  trend     Trend?        // UP, DOWN, STABLE
  sortOrder Int           @default(0)
  note      String?
  createdAt DateTime      @default(now())
  updatedAt DateTime      @updatedAt

  // Relations
  meetingId String
  meeting   MorningMeeting @relation(fields: [meetingId], references: [id], onDelete: Cascade)

  @@index([meetingId])
  @@index([category])
  @@index([sortOrder])
  @@index([status])
}

model MorningMeetingAction {
  id          String       @id @default(cuid())
  title       String
  description String?      @db.Text
  dueDate     DateTime?    @db.Date
  status      ActionStatus @default(OPEN)
  priority    Priority     @default(MEDIUM)
  completedAt DateTime?
  createdAt   DateTime     @default(now())
  updatedAt   DateTime     @updatedAt

  // Relations
  meetingId   String
  meeting     MorningMeeting @relation(fields: [meetingId], references: [id], onDelete: Cascade)
  assigneeId  String?
  assignee    User?          @relation("ActionAssignee", fields: [assigneeId], references: [id])

  @@index([meetingId])
  @@index([assigneeId])
  @@index([status])
  @@index([priority])
  @@index([dueDate])
}

// =============================================================================
// LEAN MODELS - Skill Matrix
// =============================================================================

model Skill {
  id          String  @id @default(cuid())
  name        String
  description String?
  category    String?
  isActive    Boolean @default(true)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  // Relations
  departmentId String?
  department   Department?        @relation(fields: [departmentId], references: [id])
  entries      SkillMatrixEntry[]

  @@unique([name, departmentId])
  @@index([departmentId])
  @@index([category])
}

model SkillMatrixEntry {
  id         String     @id @default(cuid())
  level      SkillLevel @default(NONE)
  assessedAt DateTime   @default(now())
  note       String?
  createdAt  DateTime   @default(now())
  updatedAt  DateTime   @updatedAt

  // Relations
  employeeId   String
  employee     Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
  skillId      String
  skill        Skill    @relation(fields: [skillId], references: [id], onDelete: Cascade)
  assessedById String?
  assessedBy   User?    @relation("SkillAssessedBy", fields: [assessedById], references: [id])

  @@unique([employeeId, skillId])
  @@index([employeeId])
  @@index([skillId])
  @@index([assessedById])
  @@index([level])
}

// =============================================================================
// USER PREFERENCES
// =============================================================================

model UserPreference {
  id              String   @id @default(cuid())
  userId          String   @unique
  user            User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  theme           String   @default("system") // "light", "dark", "system"
  language        String   @default("de")     // "de", "en"
  dashboardLayout Json?                       // Array of widget configurations
  notifications   Json?                       // Notification preferences
  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  @@index([userId])
}

// =============================================================================
// AUDIT LOGGING
// =============================================================================

model AuditLog {
  id         String   @id @default(cuid())
  userId     String
  user       User     @relation(fields: [userId], references: [id])
  action     String   // CREATE, UPDATE, DELETE, LOGIN, LOGOUT, etc.
  entity     String   // User, Department, Employee, etc.
  entityId   String?
  oldData    Json?
  newData    Json?
  ipAddress  String?
  userAgent  String?
  createdAt  DateTime @default(now())

  @@index([userId])
  @@index([entity, entityId])
  @@index([action])
  @@index([createdAt])
}

// =============================================================================
// SYSTEM SETTINGS
// =============================================================================

model SystemSetting {
  id          String   @id @default(cuid())
  key         String   @unique
  value       String
  category    String
  description String?
  valueType   String   @default("string")
  isSecret    Boolean  @default(false)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@index([category])
}
