import {
  Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn, OneToMany,
} from 'typeorm';
import { User } from './User.entity';
import { EventType } from './EventType.entity';
import { CalendarEventSync } from './CalendarEventSync.entity';

export type BookingStatus = 'pending' | 'confirmed' | 'cancelled' | 'failed';
export type MeetingOutcome = 'pending' | 'held' | 'no_show' | 'unknown';

@Entity('bookings')
export class Booking {
  @PrimaryColumn('char', { length: 36 })
  id!: string;

  @Column({ name: 'user_id', type: 'char', length: 36 })
  userId!: string;

  @Column({ name: 'event_type_id', type: 'char', length: 36 })
  eventTypeId!: string;

  @Column({ name: 'guest_name', length: 255 })
  guestName!: string;

  @Column({ name: 'guest_email', length: 255 })
  guestEmail!: string;

  @Column({ name: 'guest_timezone', length: 64 })
  guestTimezone!: string;

  @Column({ name: 'start_time', type: 'datetime', precision: 3 })
  startTime!: Date;

  @Column({ name: 'end_time', type: 'datetime', precision: 3 })
  endTime!: Date;

  @Column({ name: 'custom_answers', type: 'json', default: () => "'{}'" })
  customAnswers!: Record<string, string>;

  @Column({
    type: 'enum',
    enum: ['pending', 'confirmed', 'cancelled', 'failed'],
    default: 'pending',
  })
  status!: BookingStatus;

  @Column({ name: 'cancel_token_hash', length: 255 })
  cancelTokenHash!: string;

  @Column({ name: 'cancelled_at', type: 'datetime', precision: 3, nullable: true })
  cancelledAt!: Date | null;

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

  @Column({ name: 'idempotency_key', type: 'varchar', length: 64, nullable: true, unique: true })
  idempotencyKey!: string | null;

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

  @Column({
    name: 'meeting_outcome',
    type: 'enum',
    enum: ['pending', 'held', 'no_show', 'unknown'],
    default: 'pending',
    nullable: true,
  })
  meetingOutcome!: MeetingOutcome | null;

  @Column({ name: 'host_rating', type: 'tinyint', unsigned: true, nullable: true })
  hostRating!: number | null;

  @Column({ name: 'guest_rating', type: 'tinyint', unsigned: true, nullable: true })
  guestRating!: number | null;

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

  @Column({ name: 'reminder_24h_sent_at', type: 'datetime', precision: 3, nullable: true })
  reminder24hSentAt!: Date | null;

  @Column({ name: 'reminder_1h_sent_at', type: 'datetime', precision: 3, nullable: true })
  reminder1hSentAt!: Date | null;

  @Column({ name: 'follow_up_sent_at', type: 'datetime', precision: 3, nullable: true })
  followUpSentAt!: Date | null;

  @Column({ name: 'post_meeting_survey_sent_at', type: 'datetime', precision: 3, nullable: true })
  postMeetingSurveySentAt!: Date | null;

  @Column({ name: 'meeting_outcome_at', type: 'datetime', precision: 3, nullable: true })
  meetingOutcomeAt!: Date | null;

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

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

  @ManyToOne(() => User, (u) => u.bookings, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'user_id' })
  user!: User;

  @ManyToOne(() => EventType, (et) => et.bookings, { onDelete: 'RESTRICT' })
  @JoinColumn({ name: 'event_type_id' })
  eventType!: EventType;

  @OneToMany(() => CalendarEventSync, (s) => s.booking)
  calendarSyncs!: CalendarEventSync[];
}
