import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  ManyToOne,
  JoinColumn,
} from 'typeorm';
import { User } from './user.entity';
import { ProgramRegistration } from './program-registration.entity';
import { Program } from './program.entity';
import { ProgramSession } from './program-session.entity';
import { AttendanceEvent } from '../interfaces/attendance-event.interface';

@Entity('program_user_attendance')
export class ProgramUserAttendance {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column({ name: 'user_id', type: 'int', nullable: true })
  userId: number;

  @ManyToOne(() => User, { nullable: true })
  @JoinColumn({ name: 'user_id' })
  user: User;

  @Column({ name: 'registration_id', type: 'bigint', nullable: true })
  registrationId: number;

  @ManyToOne(() => ProgramRegistration, { nullable: true })
  @JoinColumn({ name: 'registration_id' })
  registration: ProgramRegistration;

  @Column({ name: 'registration_seq_number', type: 'varchar', length: 50, nullable: true })
  registrationSeqNumber: string;

  @Column({ name: 'program_id', type: 'int', nullable: true })
  programId: number;

  @ManyToOne(() => Program, { nullable: true })
  @JoinColumn({ name: 'program_id' })
  program: Program;

  @Column({ name: 'session_id', type: 'int', nullable: true })
  sessionId: number;

  @ManyToOne(() => ProgramSession, { nullable: true })
  @JoinColumn({ name: 'session_id' })
  session: ProgramSession;

  @Column({ name: 'uuid', type: 'varchar', length: 255, nullable: true })
  uuid: string;

  @Column({ name: 'status', type: 'varchar', length: 255, nullable: true })
  status: string;

  @Column({ name: 'full_name', type: 'varchar', length: 255, nullable: true })
  fullName: string;

  @Column({ name: 'email', type: 'varchar', length: 255, nullable: true })
  email: string;

  @Column({ name: 'mobile', type: 'varchar', length: 50, nullable: true })
  mobile: string;

  @Column({ name: 'rm_name', type: 'varchar', length: 255, nullable: true })
  rmName: string;

  @Column({ name: 'other_rm_name', type: 'varchar', length: 255, nullable: true })
  otherRmName: string;

  @Column({ name: 'qr_url', type: 'text', nullable: true })
  qrUrl: string;

  @Column({ name: 'is_attended', type: 'boolean', default: false })
  isAttended: boolean;

  @Column({ name: 'is_manually_checked_in', type: 'boolean', default: false })
  isManuallyCheckedIn: boolean;

  @Column({ name: 'checked_in_at', type: 'timestamptz', nullable: true })
  checkedInAt: Date | null;

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

  @ManyToOne(() => User, { nullable: true })
  @JoinColumn({ name: 'checked_in_by_user_id' })
  checkedInByUser: User;

  // ---- Join-time client metadata, captured on JOIN_CLICK and merged into
  // hdb_zoom_analytics during reconciliation (platform/mode breakdowns). ----
  @Column({ name: 'mode_of_joining', type: 'varchar', length: 50, nullable: true })
  modeOfJoining: string | null;

  @Column({ name: 'device_type', type: 'varchar', length: 100, nullable: true })
  deviceType: string | null;

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

  // ---- "Join with others": a companion credited via another person's device.
  // join_with_others marks the companion; joined_with_registration_id links back
  // to the primary joiner's registration. ----
  @Column({ name: 'join_with_others', type: 'boolean', default: false })
  joinWithOthers: boolean;

  @Column({ name: 'joined_with_registration_id', type: 'bigint', nullable: true })
  joinedWithRegistrationId: number | null;

  // ---- Online attendance: append-only event log across all sources
  // (JOIN_CLICK, ZOOM_WEBHOOK, MANUAL_ADMIN, QR_SCAN). Summary flags above
  // (isAttended, checkedInAt) are set on the first event. ----
  @Column({ name: 'attendance_events', type: 'jsonb', default: () => "'[]'" })
  attendanceEvents: AttendanceEvent[];

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz', default: () => 'now()' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz', default: () => 'now()' })
  updatedAt: Date;

  @Column({ name: 'created_by', type: 'int', nullable: true })
  createdBy: number;

  @Column({ name: 'updated_by', type: 'int', nullable: true })
  updatedBy: number;

  constructor(partial: Partial<ProgramUserAttendance>) {
    Object.assign(this, partial);
  }
}
