import {
  Column,
  CreateDateColumn,
  Entity,
  Index,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { User } from '../../user/entities/user.entity';
import { Meeting } from './meeting.entity';

export enum InviteScope {
  /**
   * The token alone grants entry. Convenient, but a forwarded WhatsApp
   * message lets anyone into the meeting.
   */
  PUBLIC = 'PUBLIC',
  /**
   * Token plus a one-time code sent to the invitee's mobile. A leaked link is
   * useless. Recommended for anything with commercially sensitive findings.
   */
  VERIFIED = 'VERIFIED',
  /** Token only works for a logged-in QRS user. */
  AUTHENTICATED = 'AUTHENTICATED',
}

export enum InviteChannel {
  WHATSAPP = 'WHATSAPP',
  EMAIL = 'EMAIL',
  SMS = 'SMS',
  LINK = 'LINK',
}

export enum InviteStatus {
  PENDING = 'PENDING',
  SENT = 'SENT',
  OPENED = 'OPENED',
  JOINED = 'JOINED',
  EXPIRED = 'EXPIRED',
  REVOKED = 'REVOKED',
}

/**
 * One invite = one link = one recipient.
 *
 * Deliberately not one link shared with everyone: per-recipient tokens give
 * you the sent / opened / joined trail, which matters when a client says they
 * never received it.
 */
@Entity('meeting_invites')
export class MeetingInvite {
  @PrimaryGeneratedColumn()
  id: number;

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

  @ManyToOne(() => Meeting, (m) => m.invites, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'meeting_id' })
  meeting: Meeting;

  /** the part after /j/ — short, URL-safe, unguessable */
  @Index({ unique: true })
  @Column({ type: 'varchar', length: 64 })
  token: string;

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

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

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

  /** set when inviting an existing QRS user rather than an outside guest */
  @Column({ type: 'int', nullable: true })
  recipient_user_id: number | null;

  @ManyToOne(() => User, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'recipient_user_id' })
  recipient_user: User | null;

  @Column({
    type: 'enum',
    enum: InviteScope,
    default: InviteScope.VERIFIED,
  })
  scope: InviteScope;

  @Column({
    type: 'enum',
    enum: InviteChannel,
    default: InviteChannel.LINK,
  })
  channel: InviteChannel;

  @Index()
  @Column({
    type: 'enum',
    enum: InviteStatus,
    default: InviteStatus.PENDING,
  })
  status: InviteStatus;

  /** role the invitee will hold once they join */
  @Column({ type: 'varchar', length: 20, default: 'CLIENT' })
  grant_role: string;

  @Column({ type: 'datetime' })
  expires_at: Date;

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

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

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

  /** one-time code for VERIFIED scope, hashed — never stored in the clear */
  @Column({ type: 'varchar', length: 128, nullable: true })
  otp_hash: string | null;

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

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

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

  @ManyToOne(() => User, { onDelete: 'RESTRICT' })
  @JoinColumn({ name: 'created_by_id' })
  created_by: User;

  @CreateDateColumn()
  created_at: Date;
}
