import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

export interface ScannerLockData {
  eventId: string;
  pin: string;
  organizerEmail: string;
  eventTitle: string;
  eventStartTime: string;
}

export interface UnlockAttemptData {
  eventId: string;
  pin: string;
  ipAddress?: string;
  userAgent?: string;
  deviceInfo?: string;
}

export async function hashPin(pin: string): Promise<string> {
  if (!pin || pin.length !== 4 || !/^\d{4}$/.test(pin)) {
    throw new Error('PIN must be exactly 4 digits');
  }
  
  return await bcrypt.hash(pin, SALT_ROUNDS);
}

export async function verifyPin(pin: string, hash: string): Promise<boolean> {
  if (!pin || pin.length !== 4 || !/^\d{4}$/.test(pin)) {
    return false;
  }
  
  try {
    return await bcrypt.compare(pin, hash);
  } catch (error) {

    return false;
  }
}

export function generateRandomPin(): string {
  return Math.floor(Math.random() * 10000).toString().padStart(4, '0');
}

export function validatePin(pin: string): boolean {
  return /^\d{4}$/.test(pin);
}

export function getDeviceInfo(userAgent?: string): string {
  if (!userAgent) return 'Unknown device';
  
  const device = userAgent.includes('Mobile') ? 'Mobile' : 'Desktop';
  const browser = userAgent.includes('Chrome') ? 'Chrome' : 
                  userAgent.includes('Firefox') ? 'Firefox' : 
                  userAgent.includes('Safari') ? 'Safari' : 'Unknown';
  
  return `${device} - ${browser}`;
}

export interface ScannerLockConfig {
  lockTimeoutMinutes?: number;
  maxUnlockAttempts?: number;
  lockoutDurationMinutes?: number;
}

export const DEFAULT_SCANNER_LOCK_CONFIG: ScannerLockConfig = {
  lockTimeoutMinutes: 1440, // 24 hours
  maxUnlockAttempts: 5,
  lockoutDurationMinutes: 15
};

export function shouldLockExpire(createdAt: string, config: ScannerLockConfig = DEFAULT_SCANNER_LOCK_CONFIG): boolean {
  const lockTime = new Date(createdAt);
  const now = new Date();
  const expirationTime = new Date(lockTime.getTime() + (config.lockTimeoutMinutes! * 60 * 1000));
  
  return now > expirationTime;
}