// Mana symbol utility for Magic: The Gathering cards
// Using Scryfall's symbology API: https://scryfall.com/docs/api/card-symbols/parse-mana

// Cache for parsed mana costs to avoid repeated API calls
const manaCache = new Map();

// Fallback symbol mapping for offline/error cases
const FALLBACK_SYMBOLS = {
  // Basic mana costs
  '{W}': { symbol: 'W', color: '#FFFBD5', name: 'White' },
  '{U}': { symbol: 'U', color: '#0E68AB', name: 'Blue' },
  '{B}': { symbol: 'B', color: '#150B00', name: 'Black' },
  '{R}': { symbol: 'R', color: '#D3202A', name: 'Red' },
  '{G}': { symbol: 'G', color: '#00733E', name: 'Green' },
  '{C}': { symbol: 'C', color: '#BEB9B2', name: 'Colorless' },
  
  // Generic mana costs
  '{0}': { symbol: '0', color: '#BEB9B2', name: 'Zero' },
  '{1}': { symbol: '1', color: '#BEB9B2', name: 'One' },
  '{2}': { symbol: '2', color: '#BEB9B2', name: 'Two' },
  '{3}': { symbol: '3', color: '#BEB9B2', name: 'Three' },
  '{4}': { symbol: '4', color: '#BEB9B2', name: 'Four' },
  '{5}': { symbol: '5', color: '#BEB9B2', name: 'Five' },
  '{6}': { symbol: '6', color: '#BEB9B2', name: 'Six' },
  '{7}': { symbol: '7', color: '#BEB9B2', name: 'Seven' },
  '{8}': { symbol: '8', color: '#BEB9B2', name: 'Eight' },
  '{9}': { symbol: '9', color: '#BEB9B2', name: 'Nine' },
  '{10}': { symbol: '10', color: '#BEB9B2', name: 'Ten' },
  '{X}': { symbol: 'X', color: '#BEB9B2', name: 'X' },
  
  // Hybrid mana
  '{W/U}': { symbol: 'W/U', color: 'linear-gradient(135deg, #FFFBD5 50%, #0E68AB 50%)', name: 'White or Blue' },
  '{W/B}': { symbol: 'W/B', color: 'linear-gradient(135deg, #FFFBD5 50%, #150B00 50%)', name: 'White or Black' },
  '{U/B}': { symbol: 'U/B', color: 'linear-gradient(135deg, #0E68AB 50%, #150B00 50%)', name: 'Blue or Black' },
  '{U/R}': { symbol: 'U/R', color: 'linear-gradient(135deg, #0E68AB 50%, #D3202A 50%)', name: 'Blue or Red' },
  '{B/R}': { symbol: 'B/R', color: 'linear-gradient(135deg, #150B00 50%, #D3202A 50%)', name: 'Black or Red' },
  '{B/G}': { symbol: 'B/G', color: 'linear-gradient(135deg, #150B00 50%, #00733E 50%)', name: 'Black or Green' },
  '{R/G}': { symbol: 'R/G', color: 'linear-gradient(135deg, #D3202A 50%, #00733E 50%)', name: 'Red or Green' },
  '{R/W}': { symbol: 'R/W', color: 'linear-gradient(135deg, #D3202A 50%, #FFFBD5 50%)', name: 'Red or White' },
  '{G/W}': { symbol: 'G/W', color: 'linear-gradient(135deg, #00733E 50%, #FFFBD5 50%)', name: 'Green or White' },
  '{G/U}': { symbol: 'G/U', color: 'linear-gradient(135deg, #00733E 50%, #0E68AB 50%)', name: 'Green or Blue' },
};

/**
 * Parse mana cost using Scryfall's API
 * @param {string} manaCost - Raw mana cost string (can be shorthand like "2WW" or formal like "{2}{W}{W}")
 * @returns {Promise<Object>} Parsed mana cost data from Scryfall
 */
export async function parseManaCostWithScryfall(manaCost) {
  if (!manaCost) return null;
  
  // Check cache first
  if (manaCache.has(manaCost)) {
    return manaCache.get(manaCost);
  }
  
  try {
    const response = await fetch(
      `https://api.scryfall.com/symbology/parse-mana?cost=${encodeURIComponent(manaCost)}`
    );
    
    if (response.ok) {
      const data = await response.json();
      manaCache.set(manaCost, data);
      return data;
    } else {
      console.warn('Scryfall API error:', response.status);
      return null;
    }
  } catch (error) {
    console.warn('Error parsing mana cost with Scryfall:', error);
    return null;
  }
}

/**
 * Parse mana cost string and return array of symbol components
 * Uses Scryfall API when possible, falls back to local parsing
 * @param {string} manaCost - Mana cost string
 * @returns {Promise<Array>} Array of mana symbol objects
 */
export async function parseManaSymbols(manaCost) {
  if (!manaCost) return [];
  
  // Try Scryfall API first
  const scryfallData = await parseManaCostWithScryfall(manaCost);
  if (scryfallData && scryfallData.cost) {
    // Parse the normalized cost from Scryfall
    const matches = scryfallData.cost.match(/\{[^}]+\}/g);
    if (matches) {
      return matches.map(match => {
        const symbol = FALLBACK_SYMBOLS[match];
        if (symbol) {
          return {
            raw: match,
            symbol: symbol.symbol,
            color: symbol.color,
            name: symbol.name,
            scryfall_uri: `https://svgs.scryfall.io/card-symbols/${match.replace(/[{}]/g, '')}.svg`
          };
        }
        
        // Fallback for unknown symbols
        const cleanSymbol = match.replace(/[{}]/g, '');
        return {
          raw: match,
          symbol: cleanSymbol,
          color: '#BEB9B2',
          name: cleanSymbol,
          scryfall_uri: `https://svgs.scryfall.io/card-symbols/${cleanSymbol}.svg`
        };
      });
    }
  }
  
  // Fallback to local parsing if Scryfall fails
  return parseManaSymbolsLocal(manaCost);
}

/**
 * Local fallback mana cost parsing
 * @param {string} manaCost - Mana cost string
 * @returns {Array} Array of mana symbol objects
 */
function parseManaSymbolsLocal(manaCost) {
  if (!manaCost) return [];
  
  // Handle shorthand notation (like "2WW" -> "{2}{W}{W}")
  let normalizedCost = manaCost;
  
  // If it doesn't start with {, try to normalize it
  if (!normalizedCost.startsWith('{')) {
    normalizedCost = normalizedCost
      .replace(/(\d+)/g, '{$1}')  // Numbers: 2 -> {2}
      .replace(/([WUBRG])/gi, '{$1}')  // Colors: W -> {W}
      .replace(/([XYZ])/gi, '{$1}')    // Variables: X -> {X}
      .toUpperCase();
  }
  
  // Match all {symbol} patterns
  const matches = normalizedCost.match(/\{[^}]+\}/g);
  if (!matches) return [];
  
  return matches.map(match => {
    const symbol = FALLBACK_SYMBOLS[match];
    if (symbol) {
      return {
        raw: match,
        symbol: symbol.symbol,
        color: symbol.color,
        name: symbol.name,
        scryfall_uri: `https://svgs.scryfall.io/card-symbols/${match.replace(/[{}]/g, '')}.svg`
      };
    }
    
    // Fallback for unknown symbols
    const cleanSymbol = match.replace(/[{}]/g, '');
    return {
      raw: match,
      symbol: cleanSymbol,
      color: '#BEB9B2',
      name: cleanSymbol,
      scryfall_uri: `https://svgs.scryfall.io/card-symbols/${cleanSymbol}.svg`
    };
  });
}

/**
 * Get color identity from mana cost using Scryfall data
 * @param {string} manaCost - Mana cost string
 * @returns {Promise<Array>} Array of color letters
 */
export async function getColorIdentity(manaCost) {
  if (!manaCost) return [];
  
  // Try Scryfall API first
  const scryfallData = await parseManaCostWithScryfall(manaCost);
  if (scryfallData && scryfallData.colors) {
    return scryfallData.colors;
  }
  
  // Fallback to local parsing
  const colors = new Set();
  const symbols = await parseManaSymbols(manaCost);
  
  symbols.forEach(({ raw }) => {
    if (raw.includes('W')) colors.add('W');
    if (raw.includes('U')) colors.add('U');
    if (raw.includes('B')) colors.add('B');
    if (raw.includes('R')) colors.add('R');
    if (raw.includes('G')) colors.add('G');
  });
  
  return Array.from(colors);
}

/**
 * Convert single color letter to display symbol
 * @param {string} color - Single color letter (W, U, B, R, G)
 * @returns {Object} Symbol object with display properties
 */
export function getColorSymbol(color) {
  const symbolKey = `{${color}}`;
  const symbol = FALLBACK_SYMBOLS[symbolKey];
  return symbol ? {
    ...symbol,
    scryfall_uri: `https://svgs.scryfall.io/card-symbols/${color}.svg`
  } : { 
    symbol: color, 
    color: '#BEB9B2', 
    name: color,
    scryfall_uri: `https://svgs.scryfall.io/card-symbols/${color}.svg`
  };
}

/**
 * Calculate converted mana cost using Scryfall data
 * @param {string} manaCost - Mana cost string
 * @returns {Promise<number>} Converted mana cost
 */
export async function calculateCMC(manaCost) {
  if (!manaCost) return 0;
  
  // Try Scryfall API first for accurate CMC
  const scryfallData = await parseManaCostWithScryfall(manaCost);
  if (scryfallData && typeof scryfallData.cmc === 'number') {
    return scryfallData.cmc;
  }
  
  // Fallback to local calculation
  const symbols = await parseManaSymbols(manaCost);
  let cmc = 0;
  
  symbols.forEach(({ raw }) => {
    const clean = raw.replace(/[{}]/g, '');
    
    // Numeric costs
    const numMatch = clean.match(/^\d+$/);
    if (numMatch) {
      cmc += parseInt(numMatch[0]);
      return;
    }
    
    // Single mana symbols (including hybrid) count as 1
    if (clean.match(/^[WUBRG]$/) || clean.includes('/')) {
      cmc += 1;
      return;
    }
    
    // X, Y, Z count as 0 for CMC calculation
    if (clean.match(/^[XYZ]$/)) {
      return;
    }
    
    // Everything else counts as 1
    cmc += 1;
  });
  
  return cmc;
}

/**
 * Get mana cost analysis using Scryfall
 * @param {string} manaCost - Mana cost string
 * @returns {Promise<Object>} Complete mana cost analysis
 */
export async function getManaCostAnalysis(manaCost) {
  if (!manaCost) return {
    cost: '',
    cmc: 0,
    colors: [],
    colorless: true,
    monocolored: false,
    multicolored: false,
    symbols: []
  };
  
  const scryfallData = await parseManaCostWithScryfall(manaCost);
  const symbols = await parseManaSymbols(manaCost);
  
  return {
    cost: scryfallData?.cost || manaCost,
    cmc: scryfallData?.cmc || await calculateCMC(manaCost),
    colors: scryfallData?.colors || await getColorIdentity(manaCost),
    colorless: scryfallData?.colorless ?? (symbols.length === 0 || symbols.every(s => !['W', 'U', 'B', 'R', 'G'].some(c => s.raw.includes(c)))),
    monocolored: scryfallData?.monocolored ?? false,
    multicolored: scryfallData?.multicolored ?? false,
    symbols
  };
} 