/**
 * Cliente IGDB (Twitch OAuth)
 * - `searchGames(query, platform?)`
 * - `getGameById(id)`
 */
import { fetch } from 'undici';

export type MetadataGame = {
  id?: number;
  name: string;
  slug?: string;
  releaseDate?: string;
  genres?: string[];
  platforms?: any[];
  coverUrl?: string;
  source?: string;
};

const AUTH_URL = 'https://id.twitch.tv/oauth2/token';
const API_URL = 'https://api.igdb.com/v4';

let cachedToken: { token: string; expiresAt: number } | null = null;

async function getToken(): Promise<string | null> {
  if (cachedToken && Date.now() < cachedToken.expiresAt) return cachedToken.token;

  const clientId = process.env.IGDB_CLIENT_ID || process.env.TWITCH_CLIENT_ID;
  const clientSecret = process.env.IGDB_CLIENT_SECRET || process.env.TWITCH_CLIENT_SECRET;
  if (!clientId || !clientSecret) return null;

  try {
    const params = new URLSearchParams({
      client_id: clientId,
      client_secret: clientSecret,
      grant_type: 'client_credentials',
    });

    const res = await fetch(`${AUTH_URL}?${params.toString()}`, { method: 'POST' });
    if (!res.ok) return null;
    const json = await res.json();
    const token = json.access_token as string | undefined;
    const expires = Number(json.expires_in) || 0;
    if (!token) return null;
    cachedToken = { token, expiresAt: Date.now() + Math.max(0, expires - 60) * 1000 };
    return token;
  } catch (err) {
    // eslint-disable-next-line no-console
    console.debug('igdbClient.getToken error', err);
    return null;
  }
}

function mapIgdbHit(r: any): MetadataGame {
  return {
    id: r.id,
    name: r.name,
    slug: r.slug,
    releaseDate: r.first_release_date
      ? new Date(r.first_release_date * 1000).toISOString()
      : undefined,
    genres: Array.isArray(r.genres) ? r.genres : undefined,
    platforms: Array.isArray(r.platforms) ? r.platforms : undefined,
    coverUrl: r.cover?.url ?? undefined,
    source: 'igdb',
  };
}

export async function searchGames(query: string, _platform?: string): Promise<MetadataGame[]> {
  const clientId = process.env.IGDB_CLIENT_ID || process.env.TWITCH_CLIENT_ID;
  const token = await getToken();
  if (!clientId || !token) return [];

  const headers = {
    'Client-ID': clientId,
    Authorization: `Bearer ${token}`,
    Accept: 'application/json',
    'Content-Type': 'text/plain',
  } as Record<string, string>;

  const body = `search "${query}"; fields id,name,slug,first_release_date,genres,platforms,cover; limit 10;`;

  try {
    const res = await fetch(`${API_URL}/games`, { method: 'POST', headers, body });
    if (!res.ok) return [];
    const json = await res.json();
    if (!Array.isArray(json)) return [];
    return json.map(mapIgdbHit);
  } catch (err) {
    // eslint-disable-next-line no-console
    console.debug('igdbClient.searchGames error', err);
    return [];
  }
}

export async function getGameById(id: number): Promise<MetadataGame | null> {
  const clientId = process.env.IGDB_CLIENT_ID || process.env.TWITCH_CLIENT_ID;
  const token = await getToken();
  if (!clientId || !token) return null;

  const headers = {
    'Client-ID': clientId,
    Authorization: `Bearer ${token}`,
    Accept: 'application/json',
    'Content-Type': 'text/plain',
  } as Record<string, string>;

  const body = `where id = ${id}; fields id,name,slug,first_release_date,genres,platforms,cover; limit 1;`;

  try {
    const res = await fetch(`${API_URL}/games`, { method: 'POST', headers, body });
    if (!res.ok) return null;
    const json = await res.json();
    if (!Array.isArray(json) || json.length === 0) return null;
    return mapIgdbHit(json[0]);
  } catch (err) {
    // eslint-disable-next-line no-console
    console.debug('igdbClient.getGameById error', err);
    return null;
  }
}

/**
 * Metadatos:
 * Autor: GitHub Copilot
 * Última actualización: 2026-02-11
 */
