import 'server-only';

// RAWG (api.rawg.io/api) — used to fill gaps IGDB doesn't cover well
// (system requirements text, Metacritic, playtime) and as a fallback
// when a title isn't in IGDB yet.
//
// License terms that shape how this client is used (rawg.io/apidocs):
//  - Free tier requires attribution + a live backlink to RAWG wherever
//    its data/images appear (see the "Data-Sources" credit in the game
//    page footer — src/components/games/SourceCredit.tsx).
//  - Commercial free tier caps at 100k MAU / 500k pageviews/month.
//  - No redistribution: we generate original commentary from RAWG facts,
//    we never re-serve their raw JSON or bulk-export their catalog.

const BASE_URL = 'https://api.rawg.io/api';

export interface RawgGame {
  id: number;
  slug: string;
  name: string;
  released?: string; // ISO date
  background_image?: string;
  rating?: number; // 0-5
  ratings_count?: number;
  metacritic?: number | null;
  playtime?: number; // hours
  platforms?: { platform: { name: string } }[];
  genres?: { name: string }[];
  developers?: { name: string }[];
  publishers?: { name: string }[];
  esrb_rating?: { name: string } | null;
  description_raw?: string;
  website?: string;
}

interface RawgListResponse<T> {
  count: number;
  next: string | null;
  results: T[];
}

function requireApiKey(): string {
  const key = process.env.RAWG_API_KEY;
  if (!key) {
    throw new Error('Missing RAWG_API_KEY. Get one at https://rawg.io/apidocs and add it to .env');
  }
  return key;
}

async function rawgRequest<T>(path: string, params: Record<string, string | number> = {}): Promise<T> {
  const url = new URL(`${BASE_URL}${path}`);
  url.searchParams.set('key', requireApiKey());
  for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));

  const res = await fetch(url, {
    headers: {
      // RAWG asks every client to identify itself.
      'User-Agent': `${process.env.NEXT_PUBLIC_SITE_NAME ?? 'GamesJiHub'}/1.0 (+${process.env.NEXT_PUBLIC_SITE_URL ?? ''})`,
    },
    cache: 'no-store',
  });

  if (!res.ok) {
    throw new Error(`RAWG ${path} request failed: ${res.status} ${await res.text()}`);
  }
  return res.json() as Promise<T>;
}

export async function searchRawgGame(name: string): Promise<RawgGame | null> {
  const data = await rawgRequest<RawgListResponse<RawgGame>>('/games', {
    search: name,
    search_precise: 'true',
    page_size: 1,
  });
  return data.results[0] ?? null;
}

export async function getRawgGameBySlug(slug: string): Promise<RawgGame | null> {
  try {
    return await rawgRequest<RawgGame>(`/games/${slug}`);
  } catch {
    return null;
  }
}

/** Supplemental fields IGDB frequently lacks: system requirements text, Metacritic, playtime. */
export async function enrichFromRawg(gameName: string): Promise<Partial<RawgGame> | null> {
  const match = await searchRawgGame(gameName);
  if (!match) return null;
  return match;
}
