import {
  Column,
  CreateDateColumn,
  Entity,
  Index,
  JoinColumn,
  JoinTable,
  ManyToMany,
  ManyToOne,
  OneToMany,
  OneToOne,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

export enum StatusEnum {
  active = 'active',
  inactive = 'inactive',
  unverified = 'unverified',
}

export enum GeneralStatusEnum {
  active = 'active',
  inactive = 'inactive',
  deleted = 'deleted',
}

export enum NoticeStatusEnum {
  draft = 'draft',
  published = 'published',
  archived = 'archived',
}

export enum RoleEnum {
  owner = 'owner',
  admin = 'admin',
  member = 'member',
}

export enum MemberStatusEnum {
  active = 'active',
  deactivated = 'deactivated',
  terminated = 'terminated',
  deceased = 'deceased',
  resigned = 'resigned',
  deleted = 'deleted',
}

export enum MaritalStatusEnum {
  single = 'single',
  married = 'married',
  divorced = 'divorced',
  widowed = 'widowed',
}

export enum GenderEnum {
  male = 'male',
  female = 'female',
  others = 'others',
}

export enum PriorityEnum {
  low = 'low',
  medium = 'medium',
  high = 'high',
  critical = 'critical',
}

export enum AttendanceStatusEnum {
  present = 'present',
  absent = 'absent',
  late = 'late',
  half_day = 'half_day',
  on_leave = 'on_leave',
  remote = 'remote',
  check_in = 'check_in',
  on_break = 'on_break',
  holiday = 'holiday',
  weekend = 'weekend',
}

export enum AttendanceTypeEnum {
  in_office = 'in_office',
  flexible = 'flexible',
  on_leave = 'on_leave',
}

export enum BreakTypeEnum {
  lunch = 'lunch',
  time_break = 'time_break',
}

export enum DeviceChangeRequestStatusEnum {
  pending = 'pending',
  approved = 'approved',
  rejected = 'rejected',
}

export enum LeaveStatusEnum {
  pending = 'pending',
  approved = 'approved',
  rejected = 'rejected',
  cancelled = 'cancelled',
}

export enum LeaveTypeEnum {
  annual = 'annual',
  sick = 'sick',
  casual = 'casual',
  maternity = 'maternity',
  paternity = 'paternity',
  personal = 'personal',
  compensatory = 'compensatory',
  unpaid = 'unpaid',
  day_off = 'day_off',
}

export enum AttendanceRequestTypeEnum {
  off_day_work = 'off_day_work',
  correction = 'correction',
}

export enum AttendanceRequestStatusEnum {
  pending = 'pending',
  approved = 'approved',
  rejected = 'rejected',
  cancelled = 'cancelled',
}

export enum HolidayTypeEnum {
  public = 'public',
  company = 'company',
  optional = 'optional',
  religious = 'religious',
  regional = 'regional',
  observance = 'observance',
  other = 'other',
}

export enum EventTypeEnum {
  meeting = 'meeting',
  celebration = 'celebration',
  training = 'training',
  workshop = 'workshop',
  other = 'other',
}

export enum NotificationTypeEnum {
  holiday = 'HOLIDAY',
  notice = 'NOTICE',
  leave = 'LEAVE',
  attendance = 'ATTENDANCE',
  recruitment = 'RECRUITMENT',
}

export enum JobPostingStatusEnum {
  draft = 'draft',
  published = 'published',
  closed = 'closed',
}

export enum JobApplicationStatusEnum {
  applied = 'applied',
  screening = 'screening',
  interview = 'interview',
  offer = 'offer',
  rejected = 'rejected',
  hired = 'hired',
  archived = 'archived',
}

export enum JobApplicationSourceEnum {
  public_form = 'public_form',
  public_api = 'public_api',
  manual = 'manual',
}

export enum RecruitmentTaskStatusEnum {
  pending = 'pending',
  submitted = 'submitted',
  reviewed = 'reviewed',
}

export enum TenantApiKeyStatusEnum {
  active = 'active',
  revoked = 'revoked',
}

export enum NotificationTargetTypeEnum {
  member = 'MEMBER',
  department = 'DEPARTMENT',
  role = 'ROLE',
  all = 'ALL',
}

export enum OnboardingCaseStatusEnum {
  pending = 'pending',
  in_progress = 'in_progress',
  completed = 'completed',
  cancelled = 'cancelled',
}

export enum TaskOwnerTypeEnum {
  hr = 'hr',
  it = 'it',
  manager = 'manager',
  employee = 'employee',
  finance = 'finance',
}

export enum TaskStatusEnum {
  pending = 'pending',
  in_progress = 'in_progress',
  completed = 'completed',
  skipped = 'skipped',
}

export enum DocumentSigningStatusEnum {
  pending = 'pending',
  signed = 'signed',
  rejected = 'rejected',
}

export enum ProvisioningStatusEnum {
  pending = 'pending',
  requested = 'requested',
  assigned = 'assigned',
  provisioned = 'provisioned',
  confirmed = 'confirmed',
  rejected = 'rejected',
}

export enum ProbationStatusEnum {
  pending = 'pending',
  under_review = 'under_review',
  passed = 'passed',
  extended = 'extended',
  failed = 'failed',
}

export enum ProbationOutcomeEnum {
  pass = 'pass',
  extend = 'extend',
  fail = 'fail',
}

export enum OffboardingCaseStatusEnum {
  initiated = 'initiated',
  in_progress = 'in_progress',
  pending_clearance = 'pending_clearance',
  pending_settlement = 'pending_settlement',
  ready_to_close = 'ready_to_close',
  completed = 'completed',
  cancelled = 'cancelled',
}

export enum OffboardingReasonEnum {
  resignation = 'resignation',
  termination = 'termination',
  retirement = 'retirement',
  contract_end = 'contract_end',
  other = 'other',
}

export enum ExitQuestionTypeEnum {
  text = 'text',
  long_text = 'long_text',
  single_choice = 'single_choice',
  multiple_choice = 'multiple_choice',
  rating = 'rating',
}

export enum SettlementStatusEnum {
  draft = 'draft',
  calculated = 'calculated',
  under_review = 'under_review',
  approved = 'approved',
  included_in_payroll = 'included_in_payroll',
  paid = 'paid',
  cancelled = 'cancelled',
}

@Entity({ name: 'owner' })
@Index(['email'], { unique: true })
@Index(['username'], { unique: true })
export class OwnerEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', length: 191 })
  email!: string;

  @Column({ type: 'varchar', length: 191 })
  username!: string;

  @Column({ type: 'varchar', length: 191, nullable: true })
  slug!: string | null;

  @Column({ type: 'varchar', length: 191 })
  password!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  address!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  phone!: string;

  @Column({ type: 'json' })
  image!: any;

  @Column({ type: 'enum', enum: RoleEnum, default: RoleEnum.owner })
  role!: RoleEnum;

  @Column({ type: 'varchar', length: 191, nullable: true })
  otp!: string | null;

  @Column({ type: 'enum', enum: StatusEnum, default: StatusEnum.unverified })
  status!: StatusEnum;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToOne(() => CompanyEntity, (company) => company.owner)
  company?: any;

  @OneToOne(() => WorkingScheduleEntity, (schedule) => schedule.owner)
  workingSchedule?: any;

  @OneToOne(() => LeavePolicyEntity, (policy) => policy.owner)
  leavePolicy?: any;

  @OneToOne(() => AttendanceSettingsEntity, (settings) => settings.owner)
  attendanceSettings?: any;

  @OneToMany(() => MemberEntity, (member) => member.owner)
  members?: any[];

  @OneToMany(() => AttendanceEntity, (attendance) => attendance.owner)
  attendances?: any[];

  @OneToMany(() => WorkDayScheduleEntity, (schedule) => schedule.owner)
  workDaySchedules?: any[];

  @OneToMany(() => IpWhitelistEntity, (ip) => ip.owner)
  ipWhitelists?: any[];

  @OneToMany(() => QrAttendancePointEntity, (qr) => qr.owner)
  qrAttendancePoints?: any[];

  @OneToMany(() => TeacherDeviceEntity, (device) => device.owner)
  teacherDevices?: any[];

  @OneToMany(() => DeviceChangeRequestEntity, (req) => req.owner)
  deviceChangeRequests?: any[];

  @OneToMany(() => LeaveEntity, (leave) => leave.owner)
  leaves?: any[];

  @OneToMany(() => LeaveEntity, (leave) => leave.approver_owner)
  approvedLeaves?: any[];

  @OneToMany(() => HolidayEntity, (holiday) => holiday.owner)
  holidays?: any[];

  @OneToMany(() => EventEntity, (event) => event.owner)
  events?: any[];

  @OneToMany(
    () => WorkExperienceEntity,
    (workExperience) => workExperience.owner,
  )
  workExperiences?: any[];

  @OneToMany(() => EducationEntity, (education) => education.owner)
  educations?: any[];

  @OneToMany(() => DepartmentEntity, (department) => department.owner)
  departments?: any[];

  @OneToMany(() => DesignationEntity, (designation) => designation.owner)
  designations?: any[];

  @OneToMany(() => LocationEntity, (location) => location.owner)
  locations?: any[];

  @OneToMany(
    () => EmployementTypeEntity,
    (employmentType) => employmentType.owner,
  )
  employementTypes?: any[];

  @OneToMany(() => HiringSourceEntity, (hiringSource) => hiringSource.owner)
  hiringSources?: any[];

  @OneToMany(() => NoticeEntity, (notice) => notice.owner)
  notices?: any[];

  @OneToMany(() => JobPostingEntity, (jobPosting) => jobPosting.owner)
  jobPostings?: any[];

  @OneToMany(() => JobApplicationEntity, (application) => application.owner)
  jobApplications?: any[];

  @OneToMany(() => TenantApiKeyEntity, (apiKey) => apiKey.owner)
  tenantApiKeys?: any[];
}

@Entity({ name: 'company' })
@Index(['owner_id'], { unique: true })
export class CompanyEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', name: 'company_code', length: 191 })
  company_code!: string;

  @Column({ type: 'varchar', length: 191 })
  email!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  phone!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  address!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  website!: string;

  @Column({ type: 'json' })
  logo!: any;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({
    type: 'datetime',
    name: 'founded_at',
    default: () => 'CURRENT_TIMESTAMP',
  })
  founded_at!: Date;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  industry!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @OneToOne(() => OwnerEntity, (owner) => owner.company, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'working_schedule' })
@Index(['owner_id'], { unique: true })
export class WorkingScheduleEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'json', name: 'working_days', nullable: true })
  working_days!: any;

  @Column({ type: 'int', name: 'working_days_per_week', default: 5 })
  working_days_per_week!: number;

  @Column({ type: 'float', name: 'working_hours_per_day', default: 8 })
  working_hours_per_day!: number;

  @Column({
    type: 'datetime',
    name: 'office_start_time',
    default: () => 'CURRENT_TIMESTAMP',
  })
  office_start_time!: Date;

  @Column({
    type: 'datetime',
    name: 'office_end_time',
    default: () => 'CURRENT_TIMESTAMP',
  })
  office_end_time!: Date;

  @Column({ type: 'int', name: 'half_day_min_time', default: 4 })
  half_day_min_time!: number;

  @Column({ type: 'int', name: 'half_day_max_time', default: 6 })
  half_day_max_time!: number;

  @Column({
    type: 'varchar',
    name: 'timezone',
    length: 64,
    default: 'Asia/Dhaka',
  })
  timezone!: string;

  @Column({ type: 'int', name: 'monthly_correction_limit', default: 2 })
  monthly_correction_limit!: number;

  @OneToOne(() => OwnerEntity, (owner) => owner.workingSchedule, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'work_day_schedules' })
@Index(['owner_id', 'day_of_week'], { unique: true })
@Index(['owner_id'])
export class WorkDayScheduleEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.workDaySchedules, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({ type: 'int' }) // 0 = Sunday, 1 = Monday, ..., 6 = Saturday
  day_of_week!: number;

  @Column({ type: 'boolean', default: true })
  is_active!: boolean;

  @Column({ type: 'varchar', length: 5, default: '09:00' }) // HH:mm
  start_time!: string;

  @Column({ type: 'varchar', length: 5, default: '17:00' }) // HH:mm
  end_time!: string;

  @Column({ type: 'varchar', length: 5, nullable: true }) // HH:mm
  break_start!: string | null;

  @Column({ type: 'varchar', length: 5, nullable: true }) // HH:mm
  break_end!: string | null;

  @Column({ type: 'int', default: 15 }) // minutes grace period for late threshold
  grace_period_minutes!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'ip_whitelists' })
@Index(['owner_id'])
export class IpWhitelistEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.ipWhitelists, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({ type: 'varchar', length: 191 })
  label!: string; // e.g. "Campus Wi-Fi Main"

  @Column({ type: 'varchar', length: 191 })
  ip_or_cidr!: string; // e.g. "192.168.1.0/24" or "103.20.10.5"

  @Column({ type: 'boolean', default: true })
  is_active!: boolean;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'attendance_settings' })
@Index(['owner_id'], { unique: true })
export class AttendanceSettingsEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @OneToOne(() => OwnerEntity, (owner) => owner.attendanceSettings, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({
    type: 'boolean',
    name: 'enforce_ip_whitelist',
    default: false,
  })
  enforce_ip_whitelist!: boolean;

  @Column({
    type: 'boolean',
    name: 'enforce_location',
    default: false,
  })
  enforce_location!: boolean;

  @Column({
    type: 'varchar',
    name: 'location_name',
    length: 191,
    default: 'Main Campus',
  })
  location_name!: string;

  @Column({
    type: 'decimal',
    name: 'latitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  latitude!: number | null;

  @Column({
    type: 'decimal',
    name: 'longitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  longitude!: number | null;

  @Column({
    type: 'int',
    name: 'radius_meters',
    default: 100,
  })
  radius_meters!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'qr_attendance_points' })
@Index(['owner_id'])
@Index(['code'], { unique: true })
export class QrAttendancePointEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.qrAttendancePoints, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({ type: 'varchar', length: 191 })
  label!: string; // e.g. "Main Campus Gate QR"

  @Column({ type: 'varchar', length: 255, unique: true })
  code!: string; // Secure unique QR string (e.g. "QR-ATT-xxxxxxxxxxxx")

  @Column({ type: 'boolean', default: true })
  is_active!: boolean;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'leave_policy' })
@Index(['owner_id'], { unique: true })
export class LeavePolicyEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'int', name: 'annual_leave_days', default: 0 })
  annual_leave_days!: number;

  @Column({ type: 'int', name: 'sick_leave_days', default: 0 })
  sick_leave_days!: number;

  @Column({ type: 'int', name: 'casual_leave_days', default: 0 })
  casual_leave_days!: number;

  @Column({ type: 'int', name: 'maternity_leave_days', default: 0 })
  maternity_leave_days!: number;

  @Column({ type: 'int', name: 'paternity_leave_days', default: 0 })
  paternity_leave_days!: number;

  @Column({ type: 'int', name: 'personal_leave_days', default: 0 })
  personal_leave_days!: number;

  @Column({ type: 'int', name: 'compensatory_leave_days', default: 0 })
  compensatory_leave_days!: number;

  @Column({ type: 'int', name: 'unpaid_leave_days', default: 0 })
  unpaid_leave_days!: number;

  @OneToOne(() => OwnerEntity, (owner) => owner.leavePolicy, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'departments' })
@Index(['owner_id', 'department_code'], { unique: true })
@Index(['department_head_id'], { unique: true })
export class DepartmentEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', name: 'department_code', length: 191 })
  department_code!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @OneToMany(() => MemberEntity, (member) => member.department)
  members?: any[];

  @OneToOne(() => MemberEntity, (member) => member.headed_by, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'department_head_id' })
  department_head?: any;

  @Column({
    type: 'varchar',
    name: 'department_head_id',
    length: 191,
    nullable: true,
  })
  department_head_id!: string | null;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @ManyToOne(() => OwnerEntity, (owner) => owner.departments, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @ManyToMany(() => HolidayEntity, (holiday) => holiday.departments)
  holidays?: any[];

  @ManyToMany(() => NoticeEntity, (notice) => notice.departments)
  notices?: any[];
}

@Entity({ name: 'designations' })
@Index(['owner_id', 'designation_code'], { unique: true })
export class DesignationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', name: 'designation_code', length: 191 })
  designation_code!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @ManyToOne(() => OwnerEntity, (owner) => owner.designations, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.designation)
  members?: any[];
}

@Entity({ name: 'locations' })
@Index(['owner_id', 'location_code'], { unique: true })
export class LocationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', name: 'location_code', length: 191 })
  location_code!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @ManyToOne(() => OwnerEntity, (owner) => owner.locations, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.location)
  members?: any[];

  @OneToMany(() => AttendanceEntity, (attendance) => attendance.location)
  attendances?: any[];
}

@Entity({ name: 'employement_types' })
export class EmployementTypeEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @ManyToOne(() => OwnerEntity, (owner) => owner.employementTypes, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.employment_type)
  members?: any[];
}

@Entity({ name: 'hiring_sources' })
@Index(['owner_id', 'name'], { unique: true })
export class HiringSourceEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
  })
  status!: GeneralStatusEnum;

  @ManyToOne(() => OwnerEntity, (owner) => owner.hiringSources, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.hiring_source)
  members?: any[];
}

@Entity({ name: 'events' })
@Index(['owner_id'])
export class EventEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'json' })
  image!: any;

  @Column({ type: 'enum', enum: EventTypeEnum, default: EventTypeEnum.meeting })
  category!: EventTypeEnum;

  @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
  date!: Date;

  @Column({
    type: 'datetime',
    name: 'start_time',
    default: () => 'CURRENT_TIMESTAMP',
  })
  start_time!: Date;

  @Column({
    type: 'datetime',
    name: 'end_time',
    default: () => 'CURRENT_TIMESTAMP',
  })
  end_time!: Date;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  location!: string;

  @Column({ type: 'int', default: 0 })
  attendees!: number;

  @Column({
    type: 'varchar',
    name: 'event_owner',
    length: 191,
    default: 'NT/APL',
  })
  event_owner!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.events, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.events)
  members?: any[];
}

@Entity({ name: 'notices' })
@Index(['owner_id'])
export class NoticeEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  content!: string;

  @Column({ type: 'json' })
  document!: any;

  @Column({
    type: 'enum',
    enum: NoticeStatusEnum,
    default: NoticeStatusEnum.published,
  })
  status!: NoticeStatusEnum;

  @Column({ type: 'enum', enum: PriorityEnum, default: PriorityEnum.medium })
  priority!: PriorityEnum;

  @Column({
    type: 'varchar',
    name: 'created_by',
    length: 191,
    default: 'NT/APL',
  })
  created_by!: string;

  @Column({ type: 'datetime', name: 'published_at', nullable: true })
  published_at!: Date | null;

  @Column({ type: 'datetime', name: 'expire_at', nullable: true })
  expire_at!: Date | null;

  @Column({ type: 'boolean', name: 'is_pinned', default: false })
  is_pinned!: boolean;

  @Column({ type: 'boolean', name: 'required_acknowledgment', default: false })
  required_acknowledgment!: boolean;

  // ✅ CORRECT
  @ManyToMany(() => MemberEntity, (member) => member.up_notices)
  @JoinTable({
    name: '_noticeupacknowledgment',
    joinColumn: { name: 'B', referencedColumnName: 'id' }, // B = Notice.id
    inverseJoinColumn: { name: 'A', referencedColumnName: 'id' }, // A = Member.id
  })
  up_acknowledgment?: any[];

  @ManyToMany(() => MemberEntity, (member) => member.down_notices)
  @JoinTable({
    name: '_noticedownacknowledgment',
    joinColumn: { name: 'B', referencedColumnName: 'id' }, // B = Notice.id
    inverseJoinColumn: { name: 'A', referencedColumnName: 'id' }, // A = Member.id
  })
  down_acknowledgment?: any[];

  @ManyToMany(() => DepartmentEntity, (department) => department.notices)
  @JoinTable({
    name: '_noticedepartments',
    joinColumn: { name: 'B', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'A', referencedColumnName: 'id' },
  })
  departments?: any[];

  @ManyToMany(() => MemberEntity, (member) => member.notice_recipients)
  @JoinTable({
    name: '_noticemembers',
    joinColumn: { name: 'B', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'A', referencedColumnName: 'id' },
  })
  recipients?: any[];

  @ManyToOne(() => OwnerEntity, (owner) => owner.notices, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => MemberEntity, (member) => member.notices)
  members?: any[];
}

@Entity({ name: 'members' })
@Index(['department_id'])
@Index(['designation_id'])
@Index(['location_id'])
@Index(['employment_type_id'])
@Index(['hiring_source_id'])
@Index(['reporting_manager_id'])
@Index(['status'])
@Index(['owner_id'])
export class MemberEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  email!: string;

  @Column({
    type: 'varchar',
    name: 'work_email',
    length: 191,
    default: 'NT/APL',
  })
  work_email!: string;

  @Column({ type: 'varchar', name: 'employee_id', length: 191 })
  employee_id!: string;

  @Column({ type: 'json' })
  image!: any;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  nickname!: string;

  @Column({ type: 'varchar', name: 'first_name', length: 191 })
  first_name!: string;

  @Column({
    type: 'varchar',
    name: 'last_name',
    length: 191,
    default: 'NT/APL',
  })
  last_name!: string;

  @Column({ type: 'varchar', length: 191 })
  password!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  about!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  expertise!: string;

  @Column({
    type: 'varchar',
    name: 'work_phone',
    length: 191,
    default: 'NT/APL',
  })
  work_phone!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  phone!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  father_name!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  mother_name!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  emergency_contact_name!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  emergency_contact_phone!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  emergency_contact_relationship!: string;

  @Column({ type: 'enum', enum: RoleEnum, default: RoleEnum.member })
  role!: RoleEnum;

  @Column({
    type: 'varchar',
    name: 'access_role_id',
    length: 36,
    nullable: true,
  })
  access_role_id!: string | null;

  @Column({
    type: 'enum',
    enum: MaritalStatusEnum,
    name: 'marital_status',
    default: MaritalStatusEnum.single,
  })
  marital_status!: MaritalStatusEnum;

  @Column({
    type: 'varchar',
    name: 'present_address_line_one',
    length: 191,
    default: 'NT/APL',
  })
  present_address_line_one!: string;

  @Column({
    type: 'varchar',
    name: 'present_address_line_two',
    length: 191,
    default: 'NT/APL',
  })
  present_address_line_two!: string;

  @Column({
    type: 'varchar',
    name: 'present_address_city',
    length: 191,
    default: 'NT/APL',
  })
  present_address_city!: string;

  @Column({
    type: 'varchar',
    name: 'present_address_country',
    length: 191,
    default: 'NT/APL',
  })
  present_address_country!: string;

  @Column({
    type: 'varchar',
    name: 'present_address_state',
    length: 191,
    default: 'NT/APL',
  })
  present_address_state!: string;

  @Column({
    type: 'varchar',
    name: 'present_address_zip_code',
    length: 191,
    default: 'NT/APL',
  })
  present_address_zip_code!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_line_one',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_line_one!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_line_two',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_line_two!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_city',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_city!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_country',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_country!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_state',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_state!: string;

  @Column({
    type: 'varchar',
    name: 'permanent_address_zip_code',
    length: 191,
    default: 'NT/APL',
  })
  permanent_address_zip_code!: string;

  @Column({ type: 'enum', enum: GenderEnum, default: GenderEnum.male })
  gender!: GenderEnum;

  @Column({ type: 'datetime', name: 'date_of_birth', nullable: true })
  date_of_birth!: Date | null;

  @Column({
    type: 'datetime',
    name: 'date_of_joining',
    nullable: true,
    default: () => 'CURRENT_TIMESTAMP',
  })
  date_of_joining!: Date | null;

  @ManyToOne(() => DepartmentEntity, (department) => department.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'department_id' })
  department?: DepartmentEntity | null;

  @OneToOne(() => DepartmentEntity, (department) => department.department_head)
  headed_by?: DepartmentEntity | null;

  @ManyToOne(() => MemberEntity, (member) => member.reportees, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'reporting_manager_id' })
  reporting_manager?: MemberEntity | null;

  @OneToMany(() => MemberEntity, (member) => member.reporting_manager)
  reportees?: MemberEntity[];

  @Column({
    type: 'varchar',
    name: 'department_id',
    length: 191,
    nullable: true,
  })
  department_id!: string | null;

  @ManyToOne(() => DesignationEntity, (designation) => designation.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'designation_id' })
  designation?: DesignationEntity | null;

  @Column({
    type: 'varchar',
    name: 'designation_id',
    length: 191,
    nullable: true,
  })
  designation_id!: string | null;

  @ManyToOne(() => LocationEntity, (location) => location.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'location_id' })
  location?: LocationEntity | null;

  @Column({ type: 'varchar', name: 'location_id', length: 191, nullable: true })
  location_id!: string | null;

  @ManyToOne(
    () => EmployementTypeEntity,
    (employmentType) => employmentType.members,
    { nullable: true, onDelete: 'SET NULL' },
  )
  @JoinColumn({ name: 'employment_type_id' })
  employment_type?: EmployementTypeEntity | null;

  @Column({
    type: 'varchar',
    name: 'employment_type_id',
    length: 191,
    nullable: true,
  })
  employment_type_id!: string | null;

  @ManyToOne(() => HiringSourceEntity, (hiringSource) => hiringSource.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'hiring_source_id' })
  hiring_source?: HiringSourceEntity | null;

  @Column({
    type: 'varchar',
    name: 'hiring_source_id',
    length: 191,
    nullable: true,
  })
  hiring_source_id!: string | null;

  @Column({
    type: 'varchar',
    name: 'reporting_manager_id',
    length: 191,
    nullable: true,
  })
  reporting_manager_id!: string | null;

  @Column({
    type: 'enum',
    enum: MemberStatusEnum,
    default: MemberStatusEnum.active,
  })
  status!: MemberStatusEnum;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(
    () => WorkExperienceEntity,
    (workExperience) => workExperience.member,
  )
  work_experiences?: any[];

  @OneToMany(() => EducationEntity, (education) => education.member)
  educations?: any[];

  @OneToMany(() => AttendanceEntity, (attendance) => attendance.member)
  attendances?: any[];

  @OneToOne(() => TeacherDeviceEntity, (device) => device.member)
  teacher_device?: any;

  @OneToMany(() => DeviceChangeRequestEntity, (req) => req.member)
  device_change_requests?: any[];

  @OneToMany(() => LeaveEntity, (leave) => leave.member)
  leaves?: any[];

  @OneToMany(() => LeaveEntity, (leave) => leave.approver_member)
  approved_leaves?: any[];

  @ManyToOne(() => EventEntity, (event) => event.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'eventsId' })
  events?: EventEntity | null;

  @Column({ type: 'varchar', name: 'eventsId', length: 191, nullable: true })
  eventsId!: string | null;

  @ManyToOne(() => OwnerEntity, (owner) => owner.members, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @OneToMany(() => NoticeEntity, (notice) => notice.members)
  notice_entries?: NoticeEntity[];

  @ManyToOne(() => NoticeEntity, (notice) => notice.members, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'noticesId' })
  notices?: NoticeEntity | null;

  @Column({ type: 'varchar', name: 'noticesId', length: 191, nullable: true })
  noticesId!: string | null;

  @ManyToMany(() => NoticeEntity, (notice) => notice.up_acknowledgment)
  up_notices?: NoticeEntity[];

  @ManyToMany(() => NoticeEntity, (notice) => notice.down_acknowledgment)
  down_notices?: NoticeEntity[];

  @ManyToMany(() => NoticeEntity, (notice) => notice.recipients)
  notice_recipients?: NoticeEntity[];
}

@Entity({ name: 'work_experiences' })
@Index(['member_id'])
@Index(['owner_id'])
export class WorkExperienceEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => MemberEntity, (member) => member.work_experiences, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @Column({ type: 'varchar', length: 191 })
  company!: string;

  @Column({ type: 'varchar', length: 191 })
  position!: string;

  @Column({ type: 'datetime', name: 'start_date' })
  start_date!: Date;

  @Column({ type: 'datetime', name: 'end_date', nullable: true })
  end_date!: Date | null;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({ type: 'boolean', default: false })
  relevant!: boolean;

  @ManyToOne(() => OwnerEntity, (owner) => owner.workExperiences, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'educations' })
@Index(['member_id'])
@Index(['owner_id'])
export class EducationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => MemberEntity, (member) => member.educations, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @Column({ type: 'varchar', length: 191 })
  institution!: string;

  @Column({ type: 'varchar', length: 191 })
  degree!: string;

  @Column({ type: 'varchar', length: 191 })
  field!: string;

  @Column({ type: 'datetime', name: 'start_date' })
  start_date!: Date;

  @Column({ type: 'datetime', name: 'end_date', nullable: true })
  end_date!: Date | null;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({ type: 'boolean', default: false })
  relevant!: boolean;

  @ManyToOne(() => OwnerEntity, (owner) => owner.educations, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'attendances' })
@Index(['member_id', 'date'], { unique: true })
@Index(['member_id'])
@Index(['location_id'])
@Index(['owner_id'])
export class AttendanceEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => MemberEntity, (member) => member.attendances, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @Column({ type: 'date' })
  date!: string | Date;

  @Column({
    type: 'enum',
    enum: AttendanceTypeEnum,
    default: AttendanceTypeEnum.in_office,
  })
  type!: AttendanceTypeEnum;

  @Column({ type: 'datetime', name: 'check_in', nullable: true })
  check_in!: Date | null;

  @Column({ type: 'datetime', name: 'check_out', nullable: true })
  check_out!: Date | null;

  @Column({ type: 'float', name: 'work_hours', default: 0 })
  work_hours!: number;

  @Column({ type: 'float', name: 'break_hours', default: 0 })
  break_hours!: number;

  @Column({ type: 'float', name: 'net_hours', default: 0 })
  net_hours!: number;

  @Column({ type: 'float', name: 'overtime_hours', default: 0 })
  overtime_hours!: number;

  @ManyToOne(() => LocationEntity, (location) => location.attendances, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'location_id' })
  location?: LocationEntity | null;

  @Column({ type: 'varchar', name: 'location_id', length: 191, nullable: true })
  location_id!: string | null;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  note!: string;

  @Column({
    type: 'enum',
    enum: AttendanceStatusEnum,
    default: AttendanceStatusEnum.present,
  })
  status!: AttendanceStatusEnum;

  @Column({ type: 'varchar', name: 'check_in_ip', length: 191, nullable: true })
  check_in_ip!: string | null;

  @Column({ type: 'varchar', name: 'check_out_ip', length: 191, nullable: true })
  check_out_ip!: string | null;

  @Column({ type: 'varchar', name: 'device_id', length: 255, nullable: true })
  device_id!: string | null;

  @Column({
    type: 'varchar',
    name: 'attendance_method',
    length: 32,
    default: 'manual',
  })
  attendance_method!: string; // 'manual' | 'qr'

  @Column({ type: 'varchar', name: 'qr_point_id', length: 191, nullable: true })
  qr_point_id!: string | null;

  @Column({
    type: 'boolean',
    name: 'checkout_reminder_sent',
    default: false,
  })
  checkout_reminder_sent!: boolean;

  @Column({
    type: 'datetime',
    name: 'checkout_reminder_sent_at',
    nullable: true,
  })
  checkout_reminder_sent_at!: Date | null;

  @Column({
    type: 'decimal',
    name: 'check_in_latitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  check_in_latitude!: number | null;

  @Column({
    type: 'decimal',
    name: 'check_in_longitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  check_in_longitude!: number | null;

  @Column({
    type: 'int',
    name: 'check_in_distance_meters',
    nullable: true,
  })
  check_in_distance_meters!: number | null;

  @Column({
    type: 'decimal',
    name: 'check_out_latitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  check_out_latitude!: number | null;

  @Column({
    type: 'decimal',
    name: 'check_out_longitude',
    precision: 10,
    scale: 7,
    nullable: true,
  })
  check_out_longitude!: number | null;

  @Column({
    type: 'int',
    name: 'check_out_distance_meters',
    nullable: true,
  })
  check_out_distance_meters!: number | null;

  @ManyToOne(() => OwnerEntity, (owner) => owner.attendances, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'teacher_devices' })
@Index(['member_id'], { unique: true })
@Index(['device_id'])
@Index(['owner_id'])
export class TeacherDeviceEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @OneToOne(() => MemberEntity, (member) => member.teacher_device, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.teacherDevices, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({ type: 'varchar', name: 'device_id', length: 255 })
  device_id!: string;

  @Column({
    type: 'varchar',
    name: 'device_name',
    length: 255,
    nullable: true,
  })
  device_name!: string | null;

  @Column({ type: 'varchar', name: 'last_ip', length: 191, nullable: true })
  last_ip!: string | null;

  @Column({
    type: 'datetime',
    name: 'bound_at',
    default: () => 'CURRENT_TIMESTAMP',
  })
  bound_at!: Date;

  @Column({ type: 'datetime', name: 'last_active_at', nullable: true })
  last_active_at!: Date | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'device_change_requests' })
@Index(['member_id'])
@Index(['owner_id', 'status'])
export class DeviceChangeRequestEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => MemberEntity, (member) => member.device_change_requests, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.deviceChangeRequests, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({ type: 'varchar', name: 'old_device_id', length: 255 })
  old_device_id!: string;

  @Column({ type: 'varchar', name: 'new_device_id', length: 255 })
  new_device_id!: string;

  @Column({
    type: 'varchar',
    name: 'new_device_name',
    length: 255,
    nullable: true,
  })
  new_device_name!: string | null;

  @Column({ type: 'text', nullable: true })
  reason!: string | null;

  @Column({
    type: 'enum',
    enum: DeviceChangeRequestStatusEnum,
    default: DeviceChangeRequestStatusEnum.pending,
  })
  status!: DeviceChangeRequestStatusEnum;

  @Column({
    type: 'varchar',
    name: 'reviewed_by_id',
    length: 191,
    nullable: true,
  })
  reviewed_by_id!: string | null;

  @Column({ type: 'datetime', name: 'reviewed_at', nullable: true })
  reviewed_at!: Date | null;

  @Column({ type: 'text', name: 'admin_note', nullable: true })
  admin_note!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'leaves' })
@Index(['member_id'])
@Index(['owner_id'])
@Index(['approver_owner_id'])
@Index(['approver_member_id'])
export class LeaveEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => MemberEntity, (member) => member.leaves, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @Column({ type: 'datetime', name: 'start_date' })
  start_date!: Date;

  @Column({ type: 'datetime', name: 'end_date' })
  end_date!: Date;

  @Column({
    type: 'enum',
    enum: LeaveTypeEnum,
    name: 'leave_type',
    default: LeaveTypeEnum.annual,
  })
  leave_type!: LeaveTypeEnum;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  reason!: string;

  @Column({ type: 'json', nullable: true })
  document!: any;

  @ManyToOne(() => OwnerEntity, (owner) => owner.leaves, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @Column({
    type: 'enum',
    enum: LeaveStatusEnum,
    default: LeaveStatusEnum.pending,
  })
  status!: LeaveStatusEnum;

  @Column({
    type: 'varchar',
    name: 'approver_type',
    length: 191,
    nullable: true,
  })
  approver_type!: string | null;

  @ManyToOne(() => OwnerEntity, (owner) => owner.approvedLeaves, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'approver_owner_id' })
  approver_owner?: OwnerEntity | null;

  @Column({
    type: 'varchar',
    name: 'approver_owner_id',
    length: 191,
    nullable: true,
  })
  approver_owner_id!: string | null;

  @ManyToOne(() => MemberEntity, (member) => member.approved_leaves, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  @JoinColumn({ name: 'approver_member_id' })
  approver_member?: MemberEntity | null;

  @Column({
    type: 'varchar',
    name: 'approver_member_id',
    length: 191,
    nullable: true,
  })
  approver_member_id!: string | null;

  @Column({
    type: 'datetime',
    name: 'approved_at',
    default: () => 'CURRENT_TIMESTAMP',
  })
  approved_at!: Date;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'holidays' })
@Index(['owner_id'])
export class HolidayEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({
    type: 'enum',
    enum: HolidayTypeEnum,
    name: 'holiday_type',
    default: HolidayTypeEnum.public,
  })
  holiday_type!: HolidayTypeEnum;

  @Column({
    type: 'datetime',
    name: 'start_date',
    default: () => 'CURRENT_TIMESTAMP',
  })
  start_date!: Date;

  @Column({
    type: 'datetime',
    name: 'end_date',
    default: () => 'CURRENT_TIMESTAMP',
  })
  end_date!: Date;

  @Column({ type: 'boolean', name: 'is_recurring', default: false })
  is_recurring!: boolean;

  @ManyToMany(() => DepartmentEntity, (department) => department.holidays)
  @JoinTable({
    name: '_holidaydepartments',
    joinColumn: { name: 'B', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'A', referencedColumnName: 'id' },
  })
  departments?: any[];

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @ManyToOne(() => OwnerEntity, (owner) => owner.holidays, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'notifications' })
export class NotificationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text' })
  message!: string;

  @Column({
    type: 'datetime',
    name: 'start_time',
    nullable: true,
  })
  start_time!: Date | null;

  @Column({
    type: 'datetime',
    name: 'end_time',
    nullable: true,
  })
  end_time!: Date | null;

  @Column({ type: 'float', name: 'duration', nullable: true, default: 0 })
  duration!: number | null;

  @Column({ type: 'varchar', length: 191, nullable: true })
  source_id!: string | null; // leaveId, noticeId, holidayId etc

  @Column({
    type: 'enum',
    enum: NotificationTypeEnum, // HOLIDAY | NOTICE | LEAVE | ATTENDANCE
  })
  type!: NotificationTypeEnum;

  @Column({ type: 'json', nullable: true })
  meta!: any; // store holidayId, leaveId etc

  @Column({ type: 'varchar', length: 191 })
  owner_id!: string;

  @CreateDateColumn()
  created_at!: Date;

  @UpdateDateColumn()
  updated_at!: Date;
}

@Entity({ name: 'notification_targets' })
export class NotificationTargetEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @ManyToOne(() => NotificationEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'notification_id' })
  notification!: NotificationEntity;

  @Column()
  notification_id!: string;

  // target type decides how to resolve users
  @Column({
    type: 'enum',
    enum: NotificationTargetTypeEnum,
  })
  target_type!: 'MEMBER' | 'DEPARTMENT' | 'ROLE' | 'ALL';

  @Column({ type: 'json', nullable: true })
  target_value!: any;

  @CreateDateColumn()
  created_at!: Date;

  @UpdateDateColumn()
  updated_at!: Date;
}

@Entity({ name: 'notification_receivers' })
export class NotificationReceiverEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column()
  notification_id!: string;

  @ManyToOne(() => NotificationEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'notification_id' })
  notification!: NotificationEntity;

  @Column()
  member_id!: string;

  @Column({ default: false })
  is_read!: boolean;

  @Column({
    type: 'datetime',
    name: 'read_at',
    default: () => 'CURRENT_TIMESTAMP',
  })
  read_at!: Date | null;

  @CreateDateColumn()
  created_at!: Date;

  @UpdateDateColumn()
  updated_at!: Date;
}

@Entity({ name: 'access_roles' })
@Index(['owner_id', 'slug'], { unique: true })
export class AccessRoleEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  owner_id!: string;

  @ManyToOne(() => OwnerEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', length: 191 })
  slug!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  description!: string;

  @Column({ default: false })
  is_system!: boolean;

  @Column({ type: 'int', default: 0 })
  hierarchy!: number;

  @OneToMany(() => RolePermissionEntity, (permission) => permission.role)
  permissions?: RolePermissionEntity[];

  @CreateDateColumn()
  created_at!: Date;

  @UpdateDateColumn()
  updated_at!: Date;
}

@Entity({ name: 'role_permissions' })
@Index(['role_id', 'permission_key'], { unique: true })
export class RolePermissionEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  role_id!: string;

  @ManyToOne(() => AccessRoleEntity, (role) => role.permissions, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'role_id' })
  role!: AccessRoleEntity;

  @Column({ type: 'varchar', length: 191 })
  permission_key!: string;

  @Column({ type: 'varchar', length: 191 })
  permission_value!: string;

  @CreateDateColumn()
  created_at!: Date;

  @UpdateDateColumn()
  updated_at!: Date;
}

@Entity({ name: 'job_postings' })
@Index(['owner_id', 'slug'], { unique: true })
@Index(['owner_id'])
@Index(['department_id'])
export class JobPostingEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'varchar', length: 191 })
  slug!: string;

  @Column({ type: 'varchar', length: 500, default: 'NT/APL' })
  short_description!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  salary_range!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  location!: string;

  @Column({ type: 'varchar', name: 'job_type', length: 191, default: 'NT/APL' })
  job_type!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  experience!: string;

  @Column({
    type: 'varchar',
    name: 'department_id',
    length: 191,
    nullable: true,
  })
  department_id!: string | null;

  @ManyToOne(() => DepartmentEntity, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'department_id' })
  department?: DepartmentEntity | null;

  @Column({ type: 'datetime', nullable: true })
  deadline!: Date | null;

  @Column({ type: 'int', name: 'vacancy_count', default: 1 })
  vacancy_count!: number;

  @Column({ type: 'json', nullable: true })
  role_overview!: any;

  @Column({ type: 'json', name: 'basics_benefits', nullable: true })
  basics_benefits!: any;

  @Column({ type: 'json', name: 'what_youll_do', nullable: true })
  what_youll_do!: any;

  @Column({ type: 'json', name: 'what_were_looking_for', nullable: true })
  what_were_looking_for!: any;

  @Column({ type: 'json', name: 'banner_image', nullable: true })
  banner_image!: any;

  @Column({ type: 'json', name: 'icon_image', nullable: true })
  icon_image!: any;

  @Column({ type: 'json', nullable: true })
  categories!: any;

  @Column({ type: 'json', nullable: true })
  tags!: any;

  @Column({
    type: 'enum',
    enum: JobPostingStatusEnum,
    default: JobPostingStatusEnum.draft,
  })
  status!: JobPostingStatusEnum;

  @Column({
    type: 'enum',
    enum: GeneralStatusEnum,
    default: GeneralStatusEnum.active,
    name: 'record_status',
  })
  record_status!: GeneralStatusEnum;

  @ManyToOne(() => OwnerEntity, (owner) => owner.jobPostings, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(
    () => JobApplicationEntity,
    (application) => application.job_posting,
  )
  applications?: JobApplicationEntity[];
}

@Entity({ name: 'job_applications' })
@Index(['owner_id'])
@Index(['job_posting_id'])
@Index(['status'])
export class JobApplicationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'job_posting_id', length: 191 })
  job_posting_id!: string;

  @ManyToOne(() => JobPostingEntity, (job) => job.applications, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'job_posting_id' })
  job_posting!: JobPostingEntity;

  @Column({ type: 'varchar', name: 'full_name', length: 191 })
  full_name!: string;

  @Column({ type: 'varchar', length: 191 })
  email!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  phone!: string;

  @Column({ type: 'varchar', length: 191, default: 'NT/APL' })
  location!: string;

  @Column({ type: 'json', name: 'photo_url', nullable: true })
  photo_url!: any;

  @Column({ type: 'int', name: 'experience_years', default: 0 })
  experience_years!: number;

  @Column({ type: 'json', nullable: true })
  resume!: any;

  @Column({ type: 'json', nullable: true })
  skills!: any;

  @Column({ type: 'json', name: 'work_history', nullable: true })
  work_history!: any;

  @Column({
    type: 'enum',
    enum: JobApplicationStatusEnum,
    default: JobApplicationStatusEnum.applied,
  })
  status!: JobApplicationStatusEnum;

  @Column({
    type: 'enum',
    enum: JobApplicationSourceEnum,
    default: JobApplicationSourceEnum.manual,
  })
  source!: JobApplicationSourceEnum;

  @Column({
    type: 'datetime',
    name: 'applied_at',
    default: () => 'CURRENT_TIMESTAMP',
  })
  applied_at!: Date;

  @Column({ type: 'datetime', name: 'interview_at', nullable: true })
  interview_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'offer_status',
    length: 191,
    nullable: true,
  })
  offer_status!: string | null;

  @Column({ type: 'datetime', name: 'start_date', nullable: true })
  start_date!: Date | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @ManyToOne(() => OwnerEntity, (owner) => owner.jobApplications, {
    onDelete: 'RESTRICT',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => RecruitmentTaskEntity, (task) => task.application)
  tasks?: RecruitmentTaskEntity[];
}

@Entity({ name: 'recruitment_tasks' })
@Index(['application_id'])
@Index(['public_token'], { unique: true })
export class RecruitmentTaskEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({
    type: 'varchar',
    name: 'application_id',
    length: 191,
    nullable: true,
  })
  application_id!: string | null;

  @ManyToOne(() => JobApplicationEntity, (application) => application.tasks, {
    onDelete: 'CASCADE',
    nullable: true,
  })
  @JoinColumn({ name: 'application_id' })
  application!: JobApplicationEntity | null;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({ type: 'datetime', name: 'due_date', nullable: true })
  due_date!: Date | null;

  @Column({
    type: 'enum',
    enum: RecruitmentTaskStatusEnum,
    default: RecruitmentTaskStatusEnum.pending,
  })
  status!: RecruitmentTaskStatusEnum;

  @Column({ type: 'varchar', name: 'public_token', length: 191 })
  public_token!: string;

  @Column({ type: 'json', nullable: true })
  submission!: any;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'tenant_api_keys' })
@Index(['owner_id'])
@Index(['key_prefix'])
export class TenantApiKeyEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  name!: string;

  @Column({ type: 'varchar', name: 'key_prefix', length: 191 })
  key_prefix!: string;

  @Column({ type: 'varchar', name: 'secret_hash', length: 191 })
  secret_hash!: string;

  @Column({
    type: 'enum',
    enum: TenantApiKeyStatusEnum,
    default: TenantApiKeyStatusEnum.active,
  })
  status!: TenantApiKeyStatusEnum;

  @Column({ type: 'datetime', name: 'last_used_at', nullable: true })
  last_used_at!: Date | null;

  @ManyToOne(() => OwnerEntity, (owner) => owner.tenantApiKeys, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'owner_id' })
  owner!: OwnerEntity;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

// ==========================================
// ONBOARDING & OFFBOARDING MODULE ENTITIES
// ==========================================

// 1. Onboarding Templates & Tasks
@Entity({ name: 'onboarding_templates' })
@Index(['owner_id'])
export class OnboardingTemplateEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({ type: 'boolean', name: 'is_active', default: true })
  is_active!: boolean;

  @Column({ type: 'boolean', name: 'is_default', default: false })
  is_default!: boolean;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => OnboardingTemplateTaskEntity, (task) => task.template, {
    cascade: true,
  })
  tasks?: OnboardingTemplateTaskEntity[];
}

@Entity({ name: 'onboarding_template_tasks' })
@Index(['template_id'])
export class OnboardingTemplateTaskEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'template_id', length: 191 })
  template_id!: string;

  @ManyToOne(() => OnboardingTemplateEntity, (tpl) => tpl.tasks, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'template_id' })
  template!: OnboardingTemplateEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({
    type: 'enum',
    enum: TaskOwnerTypeEnum,
    default: TaskOwnerTypeEnum.hr,
  })
  owner_type!: TaskOwnerTypeEnum;

  @Column({ type: 'enum', enum: PriorityEnum, default: PriorityEnum.medium })
  priority!: PriorityEnum;

  @Column({ type: 'int', name: 'relative_due_days', default: 7 })
  relative_due_days!: number;

  @Column({ type: 'int', name: 'order_index', default: 0 })
  order_index!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

// 2. Onboarding Cases & Associated Children
@Entity({ name: 'onboarding_cases' })
@Index(['owner_id'])
@Index(['member_id'])
@Index(['status'])
export class OnboardingCaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({
    type: 'varchar',
    name: 'job_application_id',
    length: 191,
    nullable: true,
  })
  job_application_id!: string | null;

  @Column({ type: 'varchar', name: 'template_id', length: 191, nullable: true })
  template_id!: string | null;

  @Column({
    type: 'enum',
    enum: OnboardingCaseStatusEnum,
    default: OnboardingCaseStatusEnum.pending,
  })
  status!: OnboardingCaseStatusEnum;

  @Column({ type: 'datetime', name: 'start_date', nullable: true })
  start_date!: Date | null;

  @Column({ type: 'datetime', name: 'target_completion_date', nullable: true })
  target_completion_date!: Date | null;

  @Column({ type: 'datetime', name: 'completed_at', nullable: true })
  completed_at!: Date | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => OnboardingTaskEntity, (task) => task.onboarding_case, {
    cascade: true,
  })
  tasks?: OnboardingTaskEntity[];

  @OneToMany(() => OnboardingDocumentEntity, (doc) => doc.onboarding_case, {
    cascade: true,
  })
  documents?: OnboardingDocumentEntity[];

  @OneToMany(() => ProvisioningItemEntity, (item) => item.onboarding_case, {
    cascade: true,
  })
  provisioning_items?: ProvisioningItemEntity[];

  @OneToMany(() => BuddyAssignmentEntity, (buddy) => buddy.onboarding_case, {
    cascade: true,
  })
  buddies?: BuddyAssignmentEntity[];

  @OneToMany(() => OnboardingSurveyEntity, (survey) => survey.onboarding_case, {
    cascade: true,
  })
  surveys?: OnboardingSurveyEntity[];
}

@Entity({ name: 'onboarding_tasks' })
@Index(['onboarding_case_id'])
@Index(['status'])
export class OnboardingTaskEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'onboarding_case_id', length: 191 })
  onboarding_case_id!: string;

  @ManyToOne(() => OnboardingCaseEntity, (c) => c.tasks, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'onboarding_case_id' })
  onboarding_case!: OnboardingCaseEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({
    type: 'enum',
    enum: TaskOwnerTypeEnum,
    default: TaskOwnerTypeEnum.hr,
  })
  owner_type!: TaskOwnerTypeEnum;

  @Column({
    type: 'varchar',
    name: 'assigned_member_id',
    length: 191,
    nullable: true,
  })
  assigned_member_id!: string | null;

  @ManyToOne(() => MemberEntity, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'assigned_member_id' })
  assigned_member?: MemberEntity | null;

  @Column({ type: 'datetime', name: 'due_date', nullable: true })
  due_date!: Date | null;

  @Column({ type: 'enum', enum: PriorityEnum, default: PriorityEnum.medium })
  priority!: PriorityEnum;

  @Column({
    type: 'enum',
    enum: TaskStatusEnum,
    default: TaskStatusEnum.pending,
  })
  status!: TaskStatusEnum;

  @Column({ type: 'datetime', name: 'completed_at', nullable: true })
  completed_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'completed_by_id',
    length: 191,
    nullable: true,
  })
  completed_by_id!: string | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'int', name: 'order_index', default: 0 })
  order_index!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'onboarding_documents' })
@Index(['onboarding_case_id'])
export class OnboardingDocumentEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'onboarding_case_id', length: 191 })
  onboarding_case_id!: string;

  @ManyToOne(() => OnboardingCaseEntity, (c) => c.documents, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'onboarding_case_id' })
  onboarding_case!: OnboardingCaseEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({
    type: 'varchar',
    name: 'document_type',
    length: 191,
    default: 'contract',
  })
  document_type!: string;

  @Column({ type: 'varchar', name: 'file_url', length: 500, nullable: true })
  file_url!: string | null;

  @Column({ type: 'boolean', name: 'is_required', default: true })
  is_required!: boolean;

  @Column({
    type: 'enum',
    enum: DocumentSigningStatusEnum,
    default: DocumentSigningStatusEnum.pending,
  })
  status!: DocumentSigningStatusEnum;

  @Column({ type: 'datetime', name: 'signed_at', nullable: true })
  signed_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'signed_by_id',
    length: 191,
    nullable: true,
  })
  signed_by_id!: string | null;

  @Column({ type: 'json', nullable: true })
  signature_metadata!: any;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'provisioning_items' })
@Index(['onboarding_case_id'])
export class ProvisioningItemEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'onboarding_case_id', length: 191 })
  onboarding_case_id!: string;

  @ManyToOne(() => OnboardingCaseEntity, (c) => c.provisioning_items, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'onboarding_case_id' })
  onboarding_case!: OnboardingCaseEntity;

  @Column({ type: 'varchar', name: 'item_name', length: 191 })
  item_name!: string;

  @Column({
    type: 'varchar',
    name: 'item_type',
    length: 191,
    default: 'hardware',
  })
  item_type!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({
    type: 'enum',
    enum: TaskOwnerTypeEnum,
    default: TaskOwnerTypeEnum.it,
  })
  owner_type!: TaskOwnerTypeEnum;

  @Column({
    type: 'varchar',
    name: 'assigned_member_id',
    length: 191,
    nullable: true,
  })
  assigned_member_id!: string | null;

  @Column({
    type: 'enum',
    enum: ProvisioningStatusEnum,
    default: ProvisioningStatusEnum.pending,
  })
  status!: ProvisioningStatusEnum;

  @Column({
    type: 'varchar',
    name: 'serial_number',
    length: 191,
    nullable: true,
  })
  serial_number!: string | null;

  @Column({ type: 'datetime', name: 'provisioned_at', nullable: true })
  provisioned_at!: Date | null;

  @Column({ type: 'datetime', name: 'confirmed_at', nullable: true })
  confirmed_at!: Date | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'buddy_assignments' })
@Index(['onboarding_case_id'])
@Index(['member_id'])
export class BuddyAssignmentEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'onboarding_case_id', length: 191 })
  onboarding_case_id!: string;

  @ManyToOne(() => OnboardingCaseEntity, (c) => c.buddies, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'onboarding_case_id' })
  onboarding_case!: OnboardingCaseEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'buddy_member_id', length: 191 })
  buddy_member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'buddy_member_id' })
  buddy_member!: MemberEntity;

  @Column({
    type: 'varchar',
    name: 'assigned_by_id',
    length: 191,
    nullable: true,
  })
  assigned_by_id!: string | null;

  @Column({ type: 'datetime', name: 'start_date', nullable: true })
  start_date!: Date | null;

  @Column({ type: 'datetime', name: 'end_date', nullable: true })
  end_date!: Date | null;

  @Column({ type: 'varchar', length: 50, default: 'active' })
  status!: string;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'onboarding_surveys' })
@Index(['onboarding_case_id'])
@Index(['member_id'])
export class OnboardingSurveyEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'onboarding_case_id', length: 191 })
  onboarding_case_id!: string;

  @ManyToOne(() => OnboardingCaseEntity, (c) => c.surveys, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'onboarding_case_id' })
  onboarding_case!: OnboardingCaseEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'int', name: 'interval_days', default: 30 })
  interval_days!: number;

  @Column({ type: 'varchar', length: 50, default: 'scheduled' })
  status!: string;

  @Column({ type: 'datetime', name: 'sent_at', nullable: true })
  sent_at!: Date | null;

  @Column({ type: 'datetime', name: 'completed_at', nullable: true })
  completed_at!: Date | null;

  @Column({ type: 'json', nullable: true })
  responses!: any;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

// 3. Probation Entities
@Entity({ name: 'probations' })
@Index(['owner_id'])
@Index(['member_id'])
@Index(['status'])
export class ProbationEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({
    type: 'varchar',
    name: 'onboarding_case_id',
    length: 191,
    nullable: true,
  })
  onboarding_case_id!: string | null;

  @Column({ type: 'datetime', name: 'start_date' })
  start_date!: Date;

  @Column({ type: 'int', name: 'duration_months', default: 3 })
  duration_months!: number;

  @Column({ type: 'datetime', name: 'calculated_end_date' })
  calculated_end_date!: Date;

  @Column({ type: 'datetime', name: 'current_end_date' })
  current_end_date!: Date;

  @Column({
    type: 'enum',
    enum: ProbationStatusEnum,
    default: ProbationStatusEnum.pending,
  })
  status!: ProbationStatusEnum;

  @Column({ type: 'varchar', name: 'manager_id', length: 191, nullable: true })
  manager_id!: string | null;

  @ManyToOne(() => MemberEntity, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'manager_id' })
  manager?: MemberEntity | null;

  @Column({ type: 'datetime', name: 'review_due_date', nullable: true })
  review_due_date!: Date | null;

  @Column({ type: 'datetime', name: 'reviewed_at', nullable: true })
  reviewed_at!: Date | null;

  @Column({
    type: 'enum',
    enum: ProbationOutcomeEnum,
    nullable: true,
  })
  final_outcome!: ProbationOutcomeEnum | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => ProbationReviewEntity, (review) => review.probation, {
    cascade: true,
  })
  reviews?: ProbationReviewEntity[];
}

@Entity({ name: 'probation_reviews' })
@Index(['probation_id'])
export class ProbationReviewEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'probation_id', length: 191 })
  probation_id!: string;

  @ManyToOne(() => ProbationEntity, (p) => p.reviews, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'probation_id' })
  probation!: ProbationEntity;

  @Column({ type: 'datetime', name: 'previous_end_date' })
  previous_end_date!: Date;

  @Column({ type: 'int', name: 'extension_months', default: 0 })
  extension_months!: number;

  @Column({ type: 'datetime', name: 'new_end_date' })
  new_end_date!: Date;

  @Column({ type: 'datetime', name: 'review_date' })
  review_date!: Date;

  @Column({ type: 'varchar', name: 'reviewer_id', length: 191, nullable: true })
  reviewer_id!: string | null;

  @Column({
    type: 'enum',
    enum: ProbationOutcomeEnum,
    default: ProbationOutcomeEnum.extend,
  })
  outcome!: ProbationOutcomeEnum;

  @Column({ type: 'text', nullable: true })
  comments!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;
}

// 4. Offboarding Templates & Tasks
@Entity({ name: 'offboarding_templates' })
@Index(['owner_id'])
export class OffboardingTemplateEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({ type: 'boolean', name: 'is_active', default: true })
  is_active!: boolean;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => OffboardingTemplateTaskEntity, (task) => task.template, {
    cascade: true,
  })
  tasks?: OffboardingTemplateTaskEntity[];
}

@Entity({ name: 'offboarding_template_tasks' })
@Index(['template_id'])
export class OffboardingTemplateTaskEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'template_id', length: 191 })
  template_id!: string;

  @ManyToOne(() => OffboardingTemplateEntity, (tpl) => tpl.tasks, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'template_id' })
  template!: OffboardingTemplateEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({
    type: 'enum',
    enum: TaskOwnerTypeEnum,
    default: TaskOwnerTypeEnum.hr,
  })
  owner_type!: TaskOwnerTypeEnum;

  @Column({ type: 'enum', enum: PriorityEnum, default: PriorityEnum.medium })
  priority!: PriorityEnum;

  @Column({ type: 'int', name: 'relative_due_days', default: 7 })
  relative_due_days!: number;

  @Column({ type: 'int', name: 'order_index', default: 0 })
  order_index!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

// 5. Offboarding Cases & Associated Children
@Entity({ name: 'offboarding_cases' })
@Index(['owner_id'])
@Index(['member_id'])
@Index(['status'])
export class OffboardingCaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'template_id', length: 191, nullable: true })
  template_id!: string | null;

  @Column({
    type: 'varchar',
    name: 'initiated_by_id',
    length: 191,
    nullable: true,
  })
  initiated_by_id!: string | null;

  @Column({
    type: 'enum',
    enum: OffboardingReasonEnum,
    default: OffboardingReasonEnum.resignation,
  })
  reason!: OffboardingReasonEnum;

  @Column({ type: 'datetime', name: 'last_working_date' })
  last_working_date!: Date;

  @Column({ type: 'int', name: 'notice_period_days', default: 30 })
  notice_period_days!: number;

  @Column({
    type: 'enum',
    enum: OffboardingCaseStatusEnum,
    default: OffboardingCaseStatusEnum.initiated,
  })
  status!: OffboardingCaseStatusEnum;

  @Column({ type: 'datetime', name: 'completed_at', nullable: true })
  completed_at!: Date | null;

  @Column({ type: 'datetime', name: 'access_deactivated_at', nullable: true })
  access_deactivated_at!: Date | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => OffboardingTaskEntity, (task) => task.offboarding_case, {
    cascade: true,
  })
  tasks?: OffboardingTaskEntity[];

  @OneToMany(() => EquipmentReturnEntity, (eq) => eq.offboarding_case, {
    cascade: true,
  })
  equipment_returns?: EquipmentReturnEntity[];

  @OneToOne(
    () => ExitInterviewEntity,
    (interview) => interview.offboarding_case,
  )
  exit_interview?: any;

  @OneToOne(
    () => FinalSettlementEntity,
    (settlement) => settlement.offboarding_case,
  )
  final_settlement?: any;
}

@Entity({ name: 'offboarding_tasks' })
@Index(['offboarding_case_id'])
@Index(['status'])
export class OffboardingTaskEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'offboarding_case_id', length: 191 })
  offboarding_case_id!: string;

  @ManyToOne(() => OffboardingCaseEntity, (c) => c.tasks, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'offboarding_case_id' })
  offboarding_case!: OffboardingCaseEntity;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({
    type: 'enum',
    enum: TaskOwnerTypeEnum,
    default: TaskOwnerTypeEnum.hr,
  })
  owner_type!: TaskOwnerTypeEnum;

  @Column({
    type: 'varchar',
    name: 'assigned_member_id',
    length: 191,
    nullable: true,
  })
  assigned_member_id!: string | null;

  @ManyToOne(() => MemberEntity, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'assigned_member_id' })
  assigned_member?: MemberEntity | null;

  @Column({ type: 'datetime', name: 'due_date', nullable: true })
  due_date!: Date | null;

  @Column({ type: 'enum', enum: PriorityEnum, default: PriorityEnum.medium })
  priority!: PriorityEnum;

  @Column({
    type: 'enum',
    enum: TaskStatusEnum,
    default: TaskStatusEnum.pending,
  })
  status!: TaskStatusEnum;

  @Column({ type: 'datetime', name: 'completed_at', nullable: true })
  completed_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'completed_by_id',
    length: 191,
    nullable: true,
  })
  completed_by_id!: string | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'int', name: 'order_index', default: 0 })
  order_index!: number;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'equipment_returns' })
@Index(['offboarding_case_id'])
export class EquipmentReturnEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'offboarding_case_id', length: 191 })
  offboarding_case_id!: string;

  @ManyToOne(() => OffboardingCaseEntity, (c) => c.equipment_returns, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'offboarding_case_id' })
  offboarding_case!: OffboardingCaseEntity;

  @Column({ type: 'varchar', name: 'item_name', length: 191 })
  item_name!: string;

  @Column({
    type: 'varchar',
    name: 'item_type',
    length: 191,
    default: 'hardware',
  })
  item_type!: string;

  @Column({
    type: 'varchar',
    name: 'serial_number',
    length: 191,
    nullable: true,
  })
  serial_number!: string | null;

  @Column({ type: 'varchar', length: 50, default: 'good' })
  condition!: string;

  @Column({ type: 'datetime', name: 'returned_at', nullable: true })
  returned_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'received_by_id',
    length: 191,
    nullable: true,
  })
  received_by_id!: string | null;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'exit_interview_templates' })
@Index(['owner_id'])
export class ExitInterviewTemplateEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', length: 191 })
  title!: string;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @Column({ type: 'boolean', name: 'is_active', default: true })
  is_active!: boolean;

  @Column({ type: 'json', nullable: true })
  questions!: any;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

@Entity({ name: 'exit_interviews' })
@Index(['offboarding_case_id'])
@Index(['member_id'])
export class ExitInterviewEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'offboarding_case_id', length: 191 })
  offboarding_case_id!: string;

  @OneToOne(() => OffboardingCaseEntity, (c) => c.exit_interview, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'offboarding_case_id' })
  offboarding_case!: OffboardingCaseEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({ type: 'varchar', name: 'template_id', length: 191, nullable: true })
  template_id!: string | null;

  @Column({ type: 'varchar', length: 50, default: 'pending' })
  status!: string;

  @Column({ type: 'datetime', name: 'submitted_at', nullable: true })
  submitted_at!: Date | null;

  @Column({ type: 'json', nullable: true })
  responses!: any;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;
}

// 6. Final Settlement & Items
@Entity({ name: 'final_settlements' })
@Index(['owner_id'])
@Index(['offboarding_case_id'])
@Index(['member_id'])
@Index(['status'])
export class FinalSettlementEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'offboarding_case_id', length: 191 })
  offboarding_case_id!: string;

  @OneToOne(() => OffboardingCaseEntity, (c) => c.final_settlement, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'offboarding_case_id' })
  offboarding_case!: OffboardingCaseEntity;

  @Column({ type: 'varchar', name: 'member_id', length: 191 })
  member_id!: string;

  @ManyToOne(() => MemberEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'member_id' })
  member!: MemberEntity;

  @Column({
    type: 'enum',
    enum: SettlementStatusEnum,
    default: SettlementStatusEnum.draft,
  })
  status!: SettlementStatusEnum;

  @Column({ type: 'datetime', name: 'calculation_date', nullable: true })
  calculation_date!: Date | null;

  @Column({ type: 'datetime', name: 'approved_at', nullable: true })
  approved_at!: Date | null;

  @Column({
    type: 'varchar',
    name: 'approved_by_id',
    length: 191,
    nullable: true,
  })
  approved_by_id!: string | null;

  @Column({
    type: 'decimal',
    name: 'gross_settlement',
    precision: 12,
    scale: 2,
    default: 0,
  })
  gross_settlement!: number;

  @Column({
    type: 'decimal',
    name: 'total_deductions',
    precision: 12,
    scale: 2,
    default: 0,
  })
  total_deductions!: number;

  @Column({
    type: 'decimal',
    name: 'net_settlement',
    precision: 12,
    scale: 2,
    default: 0,
  })
  net_settlement!: number;

  @Column({ type: 'text', nullable: true })
  notes!: string | null;

  @Column({ type: 'varchar', name: 'owner_id', length: 191 })
  owner_id!: string;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;

  @UpdateDateColumn({ type: 'datetime', name: 'updated_at', precision: 3 })
  updated_at!: Date;

  @OneToMany(() => FinalSettlementItemEntity, (item) => item.settlement, {
    cascade: true,
  })
  items?: FinalSettlementItemEntity[];
}

@Entity({ name: 'final_settlement_items' })
@Index(['settlement_id'])
export class FinalSettlementItemEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ type: 'varchar', name: 'settlement_id', length: 191 })
  settlement_id!: string;

  @ManyToOne(() => FinalSettlementEntity, (s) => s.items, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'settlement_id' })
  settlement!: FinalSettlementEntity;

  @Column({ type: 'varchar', name: 'item_name', length: 191 })
  item_name!: string;

  @Column({
    type: 'varchar',
    name: 'item_type',
    length: 50,
    default: 'earning',
  })
  item_type!: string;

  @Column({ type: 'decimal', precision: 12, scale: 2, default: 0 })
  amount!: number;

  @Column({ type: 'text', nullable: true })
  description!: string | null;

  @CreateDateColumn({ type: 'datetime', name: 'created_at', precision: 3 })
  created_at!: Date;
}
