import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { randomBytes } from 'crypto';
import { Meeting } from '../entities/meeting.entity';

/**
 * Room codes are read aloud on calls and typed into the browser client, so
 * they avoid characters that look alike: no 0/O, no 1/I/L.
 */
const ALPHABET = '23456789ABCDEFGHJKMNPQRSTUVWXYZ';

@Injectable()
export class RoomCodeGeneratorService {
  /** MTG-20260724-K7Q2 */
  async generate(manager: EntityManager, when = new Date()): Promise<string> {
    const y = when.getFullYear();
    const m = String(when.getMonth() + 1).padStart(2, '0');
    const d = String(when.getDate()).padStart(2, '0');
    const prefix = `MTG-${y}${m}${d}`;

    for (let attempt = 0; attempt < 12; attempt++) {
      const suffix = this.randomChars(4);
      const candidate = `${prefix}-${suffix}`;
      const clash = await manager.findOne(Meeting, {
        where: { room_code: candidate },
        select: ['id'],
      });
      if (!clash) return candidate;
    }

    // vanishingly unlikely, but never hand back a duplicate
    return `${prefix}-${this.randomChars(8)}`;
  }

  /** URL-safe invite token — 128 bits of entropy, unguessable */
  inviteToken(): string {
    return randomBytes(16).toString('base64url');
  }

  /** 6-digit one-time code for VERIFIED invites */
  otp(): string {
    return String(100000 + (randomBytes(4).readUInt32BE(0) % 900000));
  }

  private randomChars(n: number): string {
    const bytes = randomBytes(n);
    let out = '';
    for (let i = 0; i < n; i++) {
      out += ALPHABET[bytes[i] % ALPHABET.length];
    }
    return out;
  }
}
