/**
 * Utility for managing Google Fonts in the application.
 * Manages the list of available fonts and handles loading them into the DOM for web preview.
 */

export const AVAILABLE_FONTS = [
  // Sans Serif
  { name: 'Inter', category: 'sans-serif', family: "'Inter', sans-serif" },
  { name: 'Roboto', category: 'sans-serif', family: "'Roboto', sans-serif" },
  { name: 'Open Sans', category: 'sans-serif', family: "'Open Sans', sans-serif" },
  { name: 'Lato', category: 'sans-serif', family: "'Lato', sans-serif" },
  { name: 'Poppins', category: 'sans-serif', family: "'Poppins', sans-serif" },
  { name: 'Montserrat', category: 'sans-serif', family: "'Montserrat', sans-serif" },
  { name: 'Oswald', category: 'sans-serif', family: "'Oswald', sans-serif" },
  { name: 'Raleway', category: 'sans-serif', family: "'Raleway', sans-serif" },
  { name: 'Nunito', category: 'sans-serif', family: "'Nunito', sans-serif" },
  { name: 'Ubuntu', category: 'sans-serif', family: "'Ubuntu', sans-serif" },
  { name: 'Source Sans 3', category: 'sans-serif', family: "'Source Sans 3', sans-serif" },
  { name: 'PT Sans', category: 'sans-serif', family: "'PT Sans', sans-serif" },
  { name: 'Work Sans', category: 'sans-serif', family: "'Work Sans', sans-serif" },
  { name: 'Rubik', category: 'sans-serif', family: "'Rubik', sans-serif" },
  
  // Serif
  { name: 'Lora', category: 'serif', family: "'Lora', serif" },
  { name: 'Playfair Display', category: 'serif', family: "'Playfair Display', serif" },
  { name: 'Merriweather', category: 'serif', family: "'Merriweather', serif" },
  { name: 'Crimson Text', category: 'serif', family: "'Crimson Text', serif" },
  { name: 'PT Serif', category: 'serif', family: "'PT Serif', serif" },
  { name: 'Bitter', category: 'serif', family: "'Bitter', serif" },
  { name: 'Libre Baskerville', category: 'serif', family: "'Libre Baskerville', serif" },
  { name: 'Arvo', category: 'serif', family: "'Arvo', serif" },
  { name: 'Noto Serif', category: 'serif', family: "'Noto Serif', serif" },
  
  // Monospace
  { name: 'Roboto Mono', category: 'monospace', family: "'Roboto Mono', monospace" },
  { name: 'IBM Plex Mono', category: 'monospace', family: "'IBM Plex Mono', monospace" },
  { name: 'Space Mono', category: 'monospace', family: "'Space Mono', monospace" },
  { name: 'Source Code Pro', category: 'monospace', family: "'Source Code Pro', monospace" },
  { name: 'Inconsolata', category: 'monospace', family: "'Inconsolata', monospace" },
  
  // System / Standard Fallbacks (Always available)
  { name: 'Helvetica', category: 'sans-serif', family: "Helvetica, Arial, sans-serif" },
  { name: 'Arial', category: 'sans-serif', family: "Arial, sans-serif" },
  { name: 'Times New Roman', category: 'serif', family: "'Times New Roman', serif" },
  { name: 'Georgia', category: 'serif', family: "Georgia, serif" },
  { name: 'Courier Prime', category: 'monospace', family: "'Courier Prime', monospace" },
  { name: 'Courier', category: 'monospace', family: "'Courier New', Courier, monospace" }
];

const loadedFonts = new Set();
const DEFAULT_WEIGHTS = ":ital,wght@0,400;0,700;1,400;1,700"; // Standard Regular + Bold + Italics

/**
 * Generates the Google Fonts URL for the requested fonts.
 * @param {string[]} fontNames - Array of font names (e.g., ['Roboto', 'Open Sans'])
 * @returns {string} The Google Fonts URL
 */
const generateGoogleFontsUrl = (fontNames) => {
  if (!fontNames || fontNames.length === 0) return '';
  
  const families = fontNames
    .map(name => AVAILABLE_FONTS.find(f => f.name === name))
    .filter(font => font && !isSystemFont(font.name))
    .map(font => {
      // Replace spaces with + for URL
      return `${font.name.replace(/\s+/g, '+')}${DEFAULT_WEIGHTS}`;
    })
    .join('&family=');

  if (!families) return '';
  
  return `https://fonts.googleapis.com/css2?family=${families}&display=swap`;
};

/**
 * Checks if a font is a standard system font that doesn't need loading.
 */
export const isSystemFont = (fontName) => {
  const systemFonts = ['Helvetica', 'Arial', 'Times New Roman', 'Georgia', 'Courier', 'Courier New', 'Verdana', 'Tahoma', 'Trebuchet MS', 'Impact'];
  return systemFonts.includes(fontName);
};

/**
 * Dynamically loads Google Fonts into the document head for Web Preview.
 * @param {string[]} fonts - Array of font names to load
 */
export const loadGoogleFonts = (fonts) => {
  if (!fonts || !Array.isArray(fonts)) return Promise.resolve();

  // Filter out system fonts and already loaded fonts
  const fontsToLoad = fonts.filter(font => {
    return !isSystemFont(font) && !loadedFonts.has(font);
  });

  if (fontsToLoad.length === 0) return Promise.resolve();

  const url = generateGoogleFontsUrl(fontsToLoad);
  if (!url) return Promise.resolve();

  return new Promise((resolve) => {
      const link = document.createElement('link');
      link.href = url;
      link.rel = 'stylesheet';
      link.onload = () => {
        fontsToLoad.forEach(font => loadedFonts.add(font));
        // Wait for document.fonts to actually be ready if possible
        if (document.fonts) {
            document.fonts.ready.then(resolve).catch(() => resolve());
        } else {
            resolve();
        }
      };
      link.onerror = (e) => {
        console.error('Error loading fonts:', fontsToLoad, e);
        resolve(); // Resolve anyway so we don't hang
      };
      document.head.appendChild(link);
  });
};

/**
 * Ensures all fonts in the list are loaded and ready.
 */
export const ensureFontsLoaded = async (fonts) => {
    await loadGoogleFonts(fonts);
    if (document.fonts) {
        await document.fonts.ready;
    }
    return true;
};

/**
 * Helper to get the full CSS font-family string for a given font name.
 */
export const getFontFamily = (fontName) => {
  const font = AVAILABLE_FONTS.find(f => f.name === fontName);
  return font ? font.family : "'Inter', sans-serif";
};

/**
 * Extracts used font families from a list of form elements/blocks.
 */
export const extractFontsFromElements = (elements) => {
  if (!elements) return [];
  const fonts = new Set();
  
  const scan = (item) => {
      if (item.styles && item.styles.fontFamily) {
         // Clean up the font family string to get just the name
         // e.g. "Roboto, sans-serif" -> "Roboto"
         const name = item.styles.fontFamily.split(',')[0].replace(/['"]/g, '').trim();
         fonts.add(name);
      }
      if (item.blocks) {
          item.blocks.forEach(scan);
      }
      if (item.content?.columns) {
          item.content.columns.forEach(col => col.forEach(scan));
      }
  };

  elements.forEach(scan);

  return Array.from(fonts);
};