import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  ManyToMany,
  JoinTable,
  JoinColumn,
  CreateDateColumn,
  UpdateDateColumn,
  Index,
  Unique,
  OneToOne,
} from 'typeorm';
import { AuditSchedule } from './audit-schedule.entity';
import { Company } from '../../companies/entities/company.entity';
import { Standard } from '../../standards/entities/standard.entity';
import { User } from '../../user/entities/user.entity';
import { AuditRequest } from '../../audit-requests/entities/audit-request.entity';

export enum AuditType {
  INITIAL = 'INITIAL',
  SURVEILLANCE = 'SURVEILLANCE',
  RECERTIFICATION = 'RECERTIFICATION',
}

export enum AuditMode {
  ONSITE = 'ONSITE',
  OFFICE = 'OFFICE',
}

export enum RowStatus {
  PENDING = 'PENDING',
  CONFIRMED = 'CONFIRMED',
  IN_PROGRESS = 'IN_PROGRESS',
  COMPLETED = 'COMPLETED',
  CANCELLED = 'CANCELLED',
  RESCHEDULED = 'RESCHEDULED',
}

export enum CancellationReason {
  CLIENT_REQUEST = 'CLIENT_REQUEST',
  AUDITOR_UNAVAILABLE = 'AUDITOR_UNAVAILABLE',
  COORDINATOR_MISTAKE = 'COORDINATOR_MISTAKE',
  EXTERNAL_EVENT = 'EXTERNAL_EVENT',
  QUALITY_ISSUE = 'QUALITY_ISSUE',
  OTHER = 'OTHER',
}

@Entity({ name: 'audit_schedule_rows' })
@Unique('uq_audit_code', ['audit_code'])
export class AuditScheduleRow {
  @PrimaryGeneratedColumn()
  id: number;

  @Index()
  @Column({ type: 'int' })
  schedule_id: number;

  @ManyToOne(() => AuditSchedule, (schedule) => schedule.rows, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'schedule_id' })
  schedule: AuditSchedule;

  @Column({ type: 'int' })
  row_no: number;

  @Index()
  @Column({ type: 'varchar', length: 30 })
  audit_code: string;

  @Index()
  @Column({ type: 'enum', enum: AuditType })
  audit_type: AuditType;

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

  @Column({ type: 'enum', enum: AuditMode, default: AuditMode.ONSITE })
  audit_mode: AuditMode;

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

  @Index()
  @Column({ type: 'int' })
  company_id: number;

  @ManyToOne(() => Company, { nullable: false })
  @JoinColumn({ name: 'company_id' })
  company: Company;

  @Index()
  @Column({ type: 'int' })
  lead_auditor_id: number;

  @ManyToOne(() => User, { nullable: false })
  @JoinColumn({ name: 'lead_auditor_id' })
  lead_auditor: User;


  // 🆕 Additional auditors (Auditor 2, 3, ...) on the same audit
  @ManyToMany(() => User)
  @JoinTable({
    name: 'audit_row_co_auditors',
    joinColumn: { name: 'row_id', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'auditor_id', referencedColumnName: 'id' },
  })
  co_auditors: User[];
  @ManyToMany(() => Standard)
  @JoinTable({
    name: 'audit_schedule_row_standards',
    joinColumn: { name: 'row_id', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'standard_id', referencedColumnName: 'id' },
  })
  standards: Standard[];

  @Column({ type: 'time', nullable: true })
  audit_time: string;

  @Column({ type: 'varchar', length: 20, nullable: true })
  audit_time_label: string;

  // 🆕 Set ONLY when a reschedule actually reassigns the lead/co-auditor(s)
  // to someone else. Lets the PREVIOUS auditor's My Audits still show this
  // audit (as "Rescheduled") instead of it silently disappearing from
  // their list the moment someone else is assigned.
  @Index()
  @Column({ type: 'int', nullable: true })
  previous_lead_auditor_id: number | null;

  // Stored as TEXT (TypeORM's `simple-json` reads/writes it as a JSON
  // string) — NOT MySQL's native JSON column type. Some MySQL drivers
  // auto-parse native JSON columns into objects, which breaks TypeORM's
  // own JSON.parse() step in the simple-json transformer.
  @Column({ type: 'simple-json', nullable: true })
  previous_co_auditor_ids: number[] | null;

  @Index()
  @Column({ type: 'enum', enum: RowStatus, default: RowStatus.PENDING })
  status: RowStatus;
  @Column({ type: 'int', nullable: true })
  audit_request_id: number | null;

  @OneToOne(() => AuditRequest, { nullable: true })
  @JoinColumn({ name: 'audit_request_id' })
  audit_request: AuditRequest | null;
  // Cancellation
  @Column({ type: 'timestamp', nullable: true })
  cancelled_at: Date | null;

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

  @ManyToOne(() => User, { nullable: true })
  @JoinColumn({ name: 'cancelled_by_id' })
  cancelled_by: User | null;

  @Column({
    type: 'enum',
    enum: CancellationReason,
    nullable: true,
  })
  cancellation_reason: CancellationReason | null;

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

  // Reschedule (unlimited, audit_code preserved)
  @Column({ type: 'date', nullable: true })
  original_audit_date: string;

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

  @Column({ type: 'text', nullable: true })
  reschedule_reason: string;

  @Column({ type: 'timestamp', nullable: true })
  last_rescheduled_at: Date;

  @Column({ type: 'text', nullable: true })
  notes: string;
  @Column({ type: 'varchar', length: 500, nullable: true })
  stg1_audit_report: string | null;

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

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

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

  @Column({ type: 'varchar', length: 500, nullable: true })
  support_docs: string | null;
  @CreateDateColumn()
  created_at: Date;

  @UpdateDateColumn()
  updated_at: Date;
}
