import { randomId } from './crypto.js';
import { key } from './redisClient.js';

const QUEUE_KEY = key('queue:zset');
const QUEUE_LOCK_KEY = key('queue:lock');

export async function enqueue(redis, userId) {
  const score = Date.now();
  await redis.zAdd(QUEUE_KEY, [{ score, value: String(userId) }]);
  return redis.zCard(QUEUE_KEY);
}

export async function leaveQueue(redis, userId) {
  return redis.zRem(QUEUE_KEY, String(userId));
}

export async function getQueueSize(redis) {
  return redis.zCard(QUEUE_KEY);
}

export async function dequeuePair(redis) {
  // Simple lock to reduce thundering herd when multi-instance
  const lockVal = randomId('lock_');
  const locked = await redis.set(QUEUE_LOCK_KEY, lockVal, { NX: true, PX: 200 });
  if (!locked) return null;
  try {
    const ids = await redis.zRange(QUEUE_KEY, 0, -1);
    if (!ids || ids.length < 2) return null;

    const firstIndex = Math.floor(Math.random() * ids.length);
    let secondIndex = Math.floor(Math.random() * (ids.length - 1));
    if (secondIndex >= firstIndex) secondIndex += 1;

    const picked = [ids[firstIndex], ids[secondIndex]];
    await redis.zRem(QUEUE_KEY, picked[0], picked[1]);
    return [Number(picked[0]), Number(picked[1])];
  } finally {
    // best-effort unlock
    const cur = await redis.get(QUEUE_LOCK_KEY);
    if (cur === lockVal) await redis.del(QUEUE_LOCK_KEY);
  }
}
