const DEFAULT_POKEMON_TCG_DATA_BASE =
  'https://raw.githubusercontent.com/PokemonTCG/pokemon-tcg-data/master';

export function getPokemonTcgDataBaseUrl() {
  return process.env.POKEMON_TCG_DATA_BASE_URL || DEFAULT_POKEMON_TCG_DATA_BASE;
}

export function pokemonSetsUrl() {
  return `${getPokemonTcgDataBaseUrl()}/sets/en.json`;
}

export function pokemonSetCardsUrl(setCode) {
  return `${getPokemonTcgDataBaseUrl()}/cards/en/${encodeURIComponent(setCode)}.json`;
}

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function githubHeaders() {
  return {
    'User-Agent': 'Deck-Hearth/1.0',
    Accept: 'application/json',
  };
}

export async function fetchWithRetry(url, maxRetries = 3, delayMs = 2000) {
  for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
    try {
      const response = await fetch(url, { headers: githubHeaders() });

      if (response.ok) {
        return response;
      }

      if (response.status === 404) {
        throw new Error(`Resource not found: ${response.status}`);
      }

      if (response.status === 504 || response.status === 503 || response.status === 429) {
        console.log(
          `[fetchWithRetry] Attempt ${attempt}: ${response.status}, retrying in ${delayMs * attempt}ms`
        );
        await delay(delayMs * attempt);
        continue;
      }

      throw new Error(`Pokemon TCG data fetch error: ${response.status}`);
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      console.log(`[fetchWithRetry] Attempt ${attempt} failed:`, error.message);
      await delay(delayMs * attempt);
    }
  }

  throw new Error('fetchWithRetry exhausted retries');
}

export async function fetchPokemonSets() {
  const response = await fetchWithRetry(pokemonSetsUrl());
  const sets = await response.json();
  return Array.isArray(sets) ? sets : [];
}

export async function fetchPokemonSetCards(setCode) {
  try {
    const response = await fetchWithRetry(pokemonSetCardsUrl(setCode));
    const cards = await response.json();
    return Array.isArray(cards) ? cards : [];
  } catch (error) {
    if (error.message.includes('404')) {
      console.warn(`[fetchPokemonSetCards] No card file for set ${setCode} in pokemon-tcg-data`);
      return [];
    }
    throw error;
  }
}

export function normalizePokemonRarity(rarity) {
  const value = rarity || 'Unknown';
  if (value.includes('Holo')) return 'Holographic';
  if (value.includes('Secret')) return 'Secret Rare';
  if (value.includes('Ultra')) return 'Ultra Rare';
  return value;
}

/**
 * Map a pokemon-tcg-data card JSON object into DB insert fields.
 */
export function mapGithubCardForInsert(card, setMeta) {
  const setCode = setMeta?.id || null;
  const setName = setMeta?.name || setCode;
  const printedTotal = setMeta?.printedTotal || setMeta?.total || null;
  const cardNumber =
    card.number && printedTotal ? `${card.number}/${printedTotal}` : card.number || null;

  return {
    externalId: card.id,
    name: card.name,
    setName,
    setCode,
    cardNumber,
    rarity: normalizePokemonRarity(card.rarity),
    cardType: card.supertype || 'Pokemon',
    types: card.types || [],
    flavorText: card.flavorText || null,
    hp: card.hp || card.attacks?.[0]?.damage || null,
    imageSmall: card.images?.small || null,
    imageLarge: card.images?.large || null,
  };
}
