/**
 * playerAuth.js — Autenticación de jugadores con token HMAC firmado.
 *
 * Flujo en 3 capas:
 *   1. Challenge de un solo uso (anti-replay desde fuera del navegador)
 *   2. POST /api/auth/login con { playerId, challengeToken } → valida contra Garena
 *   3. Devuelve authToken firmado que el frontend usa para TODAS las llamadas
 *      siguientes. El playerId NUNCA más viaja en la URL ni en el body.
 *
 * El token contiene el playerId firmado + expiry. El backend lo decodifica
 * para saber quién es el usuario sin necesidad de que él lo envíe.
 */

import crypto from 'crypto';
import { ADMIN_PASSWORD } from '../config.js';

const TOKEN_TTL_MS = 24 * 60 * 60 * 1000; // 24 horas

// Secreto para firmar tokens de jugador
const SECRET = crypto.createHash('sha256').update(`player-auth:${ADMIN_PASSWORD || 'dev-secret'}`).digest();

function sign(payload) {
  return crypto.createHmac('sha256', SECRET).update(payload).digest('base64url');
}

export function issueAuthToken(playerId) {
  const payload = Buffer.from(JSON.stringify({
    pid: String(playerId),
    iat: Date.now(),
    exp: Date.now() + TOKEN_TTL_MS,
  })).toString('base64url');
  return `${payload}.${sign(payload)}`;
}

export function verifyAuthToken(token) {
  if (!token || typeof token !== 'string' || !token.includes('.')) return null;
  const [payload, sig] = token.split('.');
  const expected = Buffer.from(sign(payload)).buffer;
  let given;
  try {
    given = Buffer.from(sig, 'base64url');
  } catch (_e) { return null; }

  if (given.length !== expected.byteLength || !crypto.timingSafeEqual(given, new Uint8Array(expected))) return null;

  try {
    const data = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
    if (!data.pid || Date.now() > data.exp) return null;
    return { playerId: String(data.pid) };
  } catch (_e) {
    return null;
  }
}
