import { Injectable } from '@nestjs/common';
import { RedisService } from '../../shared/redis/redis.service';

const TTL_SECONDS = 120;
const KEY_PREFIX = 'presence:player:';

function keyFor(userId: bigint): string {
  return `${KEY_PREFIX}${userId.toString()}`;
}

@Injectable()
export class PresenceService {
  constructor(private readonly redis: RedisService) {}

  async touch(userId: bigint): Promise<void> {
    await this.redis.set(keyFor(userId), '1', TTL_SECONDS);
  }

  async isOnline(userId: bigint): Promise<boolean> {
    return this.redis.exists(keyFor(userId));
  }

  async getOnlineCount(): Promise<number> {
    let cursor = '0';
    let count = 0;
    do {
      const [next, keys] = await this.redis.raw.scan(
        cursor,
        'MATCH',
        `${KEY_PREFIX}*`,
        'COUNT',
        200,
      );
      cursor = next;
      count += keys.length;
    } while (cursor !== '0');
    return count;
  }

  async filterOnlineIds(ids: bigint[]): Promise<Set<string>> {
    const online = new Set<string>();
    if (ids.length === 0) return online;

    const pipeline = this.redis.raw.pipeline();
    for (const id of ids) {
      pipeline.exists(keyFor(id));
    }
    const results = await pipeline.exec();
    ids.forEach((id, index) => {
      const entry = results?.[index];
      if (!entry) return;
      const [err, value] = entry;
      if (!err && value === 1) online.add(id.toString());
    });
    return online;
  }
}
