import type { ChannelProvider } from './types';
import { upsertUserIntegration } from 'officerdb';

const configKeyMap: Record<ChannelProvider, string> = {
  discord: 'discordId',
  telegram: 'telegramId',
  whatsapp: 'whatsappId',
};

type PairingEntry = {
  userId: number;
  email: string;
  provider: ChannelProvider;
  expiresAt: number;
};

const pairingCodes = new Map<string, PairingEntry>();

const CODE_TTL_MS = 10 * 60 * 1000; // 10 minutes
const CODE_LENGTH = 6;
const CODE_CHARS = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // no 0/O/1/I ambiguity

function generateCode(): string {
  let code = '';
  for (let i = 0; i < CODE_LENGTH; i++) {
    code += CODE_CHARS[Math.floor(Math.random() * CODE_CHARS.length)]!;
  }
  return code;
}

function cleanupExpiredCodes(): void {
  const now = Date.now();
  for (const [code, entry] of pairingCodes) {
    if (entry.expiresAt <= now) {
      pairingCodes.delete(code);
    }
  }
}

export function generatePairingCode(userId: number, email: string, provider: ChannelProvider): string {
  cleanupExpiredCodes();

  // Revoke any existing code for this user+provider
  for (const [code, entry] of pairingCodes) {
    if (entry.userId === userId && entry.provider === provider) {
      pairingCodes.delete(code);
    }
  }

  let code: string;
  do {
    code = generateCode();
  } while (pairingCodes.has(code));

  pairingCodes.set(code, {
    userId,
    email,
    provider,
    expiresAt: Date.now() + CODE_TTL_MS,
  });

  return code;
}

type PairingResult = {
  userId: number;
  email: string;
  provider: ChannelProvider;
};

export async function consumePairingCode(code: string, channelUserId: string): Promise<PairingResult | null> {
  const entry = pairingCodes.get(code.toUpperCase());
  if (!entry || entry.expiresAt <= Date.now()) return null;

  pairingCodes.delete(code.toUpperCase());

  await upsertUserIntegration({
    userId: entry.userId,
    provider: entry.provider,
    config: { [configKeyMap[entry.provider]]: channelUserId },
  });

  return { userId: entry.userId, email: entry.email, provider: entry.provider };
}
