import { FontOption, SiteConfig } from "../types";
import { FONT_PAIRS } from "../constants";
import JSZip from "jszip";

const getFontUrl = (fontName: string) => {
  return `https://fonts.googleapis.com/css2?family=${fontName.replace(/\s+/g, '+')}:wght@400;700&display=swap`;
};

export const generateWebsiteZip = async (config: SiteConfig) => {
  const zip = new JSZip();
  const selectedFont = FONT_PAIRS.find(f => f.name === config.fontPair) || FONT_PAIRS[0];

  // Modal CSS injection if feature enabled
  const modalCss = config.features.contactForm ? `
    .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 9999; opacity: 0; visibility: hidden; transition: all 0.3s; }
    .modal-overlay.open { opacity: 1; visibility: visible; }
    .modal-box { background: white; width: 100%; max-width: 400px; border-radius: 0.5rem; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); overflow: hidden; transform: scale(0.95); transition: transform 0.3s; }
    .modal-overlay.open .modal-box { transform: scale(1); }
    .hidden { display: none !important; }
  ` : '';

  // Modal HTML injection
  const modalHtml = config.features.contactForm ? `
    <div id="contact-modal" class="modal-overlay">
        <div class="modal-box">
            <!-- Form State -->
            <div id="modal-form-section">
                <div class="flex justify-between items-center p-4 border-b bg-gray-50">
                    <h3 class="font-bold text-gray-900">Contact Us</h3>
                    <button onclick="closeModal()" class="text-gray-400 hover:text-gray-600 font-bold text-xl">&times;</button>
                </div>
                <form onsubmit="handleContactSubmit(event)" class="p-4 space-y-4">
                    <div>
                        <label class="block text-xs font-bold text-gray-700 mb-1 uppercase">Name</label>
                        <input type="text" id="contact-name" required class="w-full p-2 border rounded text-sm outline-none focus:ring-2 focus:ring-blue-500">
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-gray-700 mb-1 uppercase">Email</label>
                        <input type="email" id="contact-email" required class="w-full p-2 border rounded text-sm outline-none focus:ring-2 focus:ring-blue-500">
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-gray-700 mb-1 uppercase">Message</label>
                        <textarea id="contact-message" required rows="3" class="w-full p-2 border rounded text-sm outline-none focus:ring-2 focus:ring-blue-500"></textarea>
                    </div>
                    <button type="submit" class="w-full py-2 text-white font-bold rounded hover:opacity-90 transition accent-bg">Send Message</button>
                </form>
            </div>
            
            <!-- Success State -->
            <div id="modal-success-section" class="hidden p-8 text-center">
                <div class="w-16 h-16 bg-green-100 text-green-600 rounded-full flex items-center justify-center mx-auto mb-4">
                    <svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
                </div>
                <h3 class="text-xl font-bold mb-2 text-gray-900">Message Sent!</h3>
                <p class="text-sm text-gray-600">We will get back to you shortly.</p>
                <button onclick="closeModal()" class="mt-6 text-blue-600 underline text-sm">Close</button>
            </div>
        </div>
    </div>

    <script>
        function openModal(e) {
            if (e) e.preventDefault();
            document.getElementById('contact-modal').classList.add('open');
            document.getElementById('modal-form-section').classList.remove('hidden');
            document.getElementById('modal-success-section').classList.add('hidden');
        }
        
        function closeModal() {
            document.getElementById('contact-modal').classList.remove('open');
        }

        function handleContactSubmit(e) {
            e.preventDefault();
            const name = document.getElementById('contact-name').value;
            const email = document.getElementById('contact-email').value;
            const message = document.getElementById('contact-message').value;

            const subject = encodeURIComponent("New Contact Form Message");
            const body = encodeURIComponent("Name: " + name + "\\nEmail: " + email + "\\n\\nMessage:\\n" + message);
            const mailtoLink = "mailto:${config.contact.email}?subject=" + subject + "&body=" + body;

            window.location.href = mailtoLink;

            document.getElementById('modal-form-section').classList.add('hidden');
            document.getElementById('modal-success-section').classList.remove('hidden');
            setTimeout(closeModal, 4000);
        }
    </script>
  ` : '';

  // --- HTML GENERATORS BASED ON LAYOUT ---

  const getHeaderHtml = () => {
      const navLinks = config.features.showNav ? `
        <nav class="flex flex-wrap gap-4 md:gap-6 font-medium opacity-90 ${config.layoutStyle === 'minimal' ? 'justify-center text-xs uppercase tracking-widest' : 'text-sm'}">
            <a href="#home" class="hover:underline hover:opacity-100">Home</a>
            <a href="#services" class="hover:underline hover:opacity-100">Services</a>
            <a href="#contact" class="hover:underline hover:opacity-100">Contact</a>
        </nav>` : '';

      let containerClasses = "max-w-4xl mx-auto flex justify-between items-center flex-wrap gap-4";
      let wrapperClasses = `py-${config.layout.spacing} px-6 shadow-md sticky top-0 z-50`;
      let btnClasses = "accent-bg text-white px-4 py-2 rounded text-sm font-bold shrink-0";
      let bgStyle = `background-color: ${config.colors.primary}; color: white;`;

      if (config.layoutStyle === 'modern') {
          bgStyle = "background-color: rgba(255,255,255,0.95); color: #111; backdrop-filter: blur(10px); border-bottom: 1px solid #eee;";
          wrapperClasses = "py-4 px-6 sticky top-0 z-50";
      } else if (config.layoutStyle === 'minimal') {
          bgStyle = `background-color: ${config.colors.background}; color: ${config.colors.text};`;
          wrapperClasses = "py-8 px-6 sticky top-0 z-50";
          containerClasses = "max-w-4xl mx-auto flex flex-col items-center gap-4";
          btnClasses = "hidden"; // No call button in header for minimal usually
      } else if (config.layoutStyle === 'bold') {
          bgStyle = `background-color: white; color: black; border-bottom: 4px solid black;`;
          btnClasses = "accent-bg text-black border-2 border-black shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] px-4 py-2 font-bold shrink-0 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none transition-all";
      } else if (config.layoutStyle === 'magazine') {
          bgStyle = "background-color: white; color: black; border-bottom: 2px solid black;";
          wrapperClasses = "py-6 px-6 sticky top-0 z-50";
          containerClasses = "max-w-6xl mx-auto flex justify-between items-center flex-wrap gap-4";
          btnClasses = "hidden";
      } else if (config.layoutStyle === 'showcase') {
          bgStyle = "background-color: transparent; color: white;";
          wrapperClasses = "absolute top-0 left-0 w-full py-6 px-8 z-50";
          containerClasses = "max-w-7xl mx-auto flex justify-between items-center flex-wrap gap-4";
          btnClasses = "bg-white text-black px-6 py-2 rounded-full font-bold shadow-md hover:scale-105 transition transform text-sm";
      }
      
      // Use base64 directly for reliability in export
      const logoHtml = config.images.favicon ? `<img src="${config.images.favicon}" alt="Logo" class="h-8 w-8 object-contain">` : '';

      return `
      <header style="${bgStyle}" class="${wrapperClasses}">
        <div class="${containerClasses}">
            <h1 class="text-2xl font-bold flex items-center gap-3" style="${config.layoutStyle === 'magazine' ? 'font-family: serif; text-transform: uppercase; letter-spacing: 0.1em;' : ''}">
                ${logoHtml}
                <span>${config.businessName}</span>
            </h1>
            ${navLinks}
            ${config.contact.phone && config.layoutStyle !== 'magazine' && config.layoutStyle !== 'minimal' ? `<a href="tel:${config.contact.phone}" class="${btnClasses}">Call Us</a>` : ''}
        </div>
      </header>`;
  };

  const getHeroHtml = () => {
      const heroImg = config.images.hero;
      
      if (config.layoutStyle === 'magazine') {
           return `
          <section id="home" class="grid grid-cols-1 md:grid-cols-12 border-b-2 border-black">
             <div class="md:col-span-5 p-12 flex flex-col justify-center bg-gray-50 text-black border-r-0 md:border-r-2 border-black min-h-[50vh]">
                <h2 class="font-bold mb-6 text-4xl leading-tight font-serif">${config.title}</h2>
                <p class="text-lg mb-8 leading-relaxed">${config.description}</p>
                <a href="#contact" class="bg-black text-white px-8 py-4 uppercase tracking-widest text-xs font-bold hover:bg-gray-800 transition inline-block text-center w-max">${config.ctaText}</a>
             </div>
             <div class="md:col-span-7 relative min-h-[400px]">
                ${heroImg ? `<img src="${heroImg}" class="absolute inset-0 w-full h-full object-cover" alt="Hero">` : '<div class="absolute inset-0 bg-gray-200"></div>'}
             </div>
          </section>`;
      } else if (config.layoutStyle === 'showcase') {
          return `
          <section id="home" class="relative w-full h-screen flex items-center justify-center overflow-hidden bg-gray-900">
             ${heroImg ? `<img src="${heroImg}" class="absolute inset-0 w-full h-full object-cover opacity-80" alt="Hero">` : '<div class="absolute inset-0 bg-gradient-to-br from-purple-900 to-black"></div>'}
             <div class="absolute inset-0 bg-black/30"></div>
             <div class="relative z-10 text-center max-w-4xl px-6 text-white">
                <h2 class="font-bold mb-6 text-5xl md:text-7xl leading-tight drop-shadow-lg">${config.title}</h2>
                <p class="text-xl md:text-2xl mb-10 opacity-90 drop-shadow-md max-w-2xl mx-auto">${config.description}</p>
                <a href="#contact" class="bg-white text-black px-10 py-4 rounded-full font-bold text-lg shadow-2xl hover:scale-105 transition transform inline-block">${config.ctaText}</a>
             </div>
          </section>`;
      } else if (config.layoutStyle === 'modern') {
          return `
          <section id="home" class="max-w-6xl mx-auto px-6 py-12 grid grid-cols-1 md:grid-cols-2 items-center gap-12" style="min-height: 60vh">
             <div class="order-2 md:order-1">
                <h2 class="font-bold mb-6 text-gray-900" style="font-size: ${config.layout.headerSize * 0.5 + 1.5}rem">${config.title}</h2>
                <p class="text-lg mb-8 opacity-80">${config.description}</p>
                <a href="#contact" class="accent-bg text-white px-8 py-3 rounded-lg font-bold shadow-lg hover:opacity-90 transition">${config.ctaText}</a>
             </div>
             <div class="order-1 md:order-2">
                ${heroImg ? `<img src="${heroImg}" class="w-full h-auto rounded-2xl shadow-xl object-cover aspect-square" alt="Hero">` : '<div class="w-full aspect-square bg-gray-200 rounded-2xl"></div>'}
             </div>
          </section>`;
      } else if (config.layoutStyle === 'minimal') {
          return `
          <section id="home" class="max-w-3xl mx-auto px-6 py-20 flex flex-col items-center text-center">
             <h2 class="font-bold mb-6 leading-tight" style="font-size: ${config.layout.headerSize * 0.5 + 1.5}rem; color: ${config.colors.text}">${config.title}</h2>
             <p class="text-lg mb-10 opacity-70">${config.description}</p>
             <a href="#contact" class="border-2 border-black px-10 py-3 text-xs uppercase tracking-widest hover:bg-black hover:text-white transition">${config.ctaText}</a>
             ${heroImg ? `<img src="${heroImg}" class="mt-16 w-full max-w-xl grayscale hover:grayscale-0 transition duration-700" alt="Hero">` : ''}
          </section>`;
      } else if (config.layoutStyle === 'bold') {
          return `
          <section id="home" class="w-full py-20 flex flex-col items-center justify-center text-center border-b-4 border-black" style="background-color: ${config.colors.primary}">
            <div class="bg-white p-8 border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] max-w-2xl mx-4">
                <h2 class="font-bold mb-4 text-black" style="font-size: ${config.layout.headerSize * 0.5 + 1.5}rem">${config.title}</h2>
                <p class="text-lg mb-6 text-black">${config.description}</p>
                <a href="#contact" class="inline-block bg-black text-white px-8 py-3 border-2 border-black font-bold uppercase hover:bg-white hover:text-black hover:shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] transition">${config.ctaText}</a>
            </div>
            ${heroImg ? `<img src="${heroImg}" class="mt-12 border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] max-w-2xl w-full h-64 object-cover" alt="Hero">` : ''}
          </section>`;
      }
      
      // Classic Fallback
      return `
      <section id="home" class="relative w-full bg-gray-100 flex items-center justify-center overflow-hidden" style="min-height: 60vh;">
        ${heroImg ? `<img src="${heroImg}" class="absolute inset-0 w-full h-full object-cover opacity-90" alt="Hero">` : '<div class="absolute inset-0 bg-gray-300"></div>'}
        <div class="relative z-10 p-8 bg-black/50 text-white text-center rounded-xl max-w-2xl mx-4">
            <h2 class="font-bold mb-4" style="font-size: ${config.layout.headerSize * 0.5 + 1.5}rem">${config.title}</h2>
            <p class="text-lg mb-6">${config.description}</p>
            <a href="#contact" class="accent-bg text-white px-8 py-3 rounded-full font-bold shadow-lg hover:opacity-90 transition">${config.ctaText}</a>
        </div>
      </section>`;
  };

  const getMainContentHtml = () => {
      // Common image styles based on layout
      let imgClass = "rounded-lg shadow-lg mb-8";
      let wrapperClass = "flex flex-col items-center text-center";
      
      if (config.layoutStyle === 'bold') {
          imgClass = "border-4 border-black shadow-[6px_6px_0px_0px_rgba(0,0,0,1)] mb-8";
      } else if (config.layoutStyle === 'magazine') {
          imgClass = "border border-black mb-8 w-full";
          wrapperClass = "border-2 border-black p-8 bg-white shadow-[4px_4px_0px_0px_rgba(0,0,0,0.1)] flex flex-col items-center text-center";
      } else if (config.layoutStyle === 'showcase') {
          wrapperClass = "flex flex-col items-center text-center max-w-5xl mx-auto py-12";
          imgClass = "rounded-xl shadow-2xl mb-12 w-full";
      }

      const section1 = `
        <div class="${wrapperClass} ${config.layoutStyle === 'modern' ? 'bg-white p-8 rounded-2xl shadow-sm md:grid md:grid-cols-2 md:gap-8 md:items-center' : ''} ${config.layoutStyle === 'magazine' ? 'md:grid md:grid-cols-2 md:gap-8 md:items-center md:text-left' : ''}">
            <p class="mb-8 leading-relaxed ${config.layoutStyle === 'modern' || config.layoutStyle === 'magazine' ? 'md:mb-0 text-left' : ''}" style="font-size: ${config.layout.textSize}px">${config.secondParagraph}</p>
            ${config.images.section1 ? `<img src="${config.images.section1}" class="${imgClass} w-full object-cover" style="${(config.layoutStyle === 'modern' || config.layoutStyle === 'magazine' || config.layoutStyle === 'showcase') ? '' : `width: ${config.layout.imageWidth}%`}" alt="Service">` : ''}
        </div>
      `;

      // Section 2
      const section2 = `
        <div class="${wrapperClass} ${config.layoutStyle === 'modern' ? 'bg-white p-8 rounded-2xl shadow-sm md:grid md:grid-cols-2 md:gap-8 md:items-center' : ''} ${config.layoutStyle === 'magazine' ? 'md:grid md:grid-cols-2 md:gap-8 md:items-center md:text-left' : ''}">
             ${config.thirdParagraph ? `<p class="mb-8 leading-relaxed ${config.layoutStyle === 'modern' || config.layoutStyle === 'magazine' ? 'md:mb-0 text-left order-2' : ''}" style="font-size: ${config.layout.textSize}px">${config.thirdParagraph}</p>` : ''}
             ${config.images.section2 ? `<img src="${config.images.section2}" class="${imgClass} ${config.layoutStyle === 'modern' || config.layoutStyle === 'magazine' ? 'order-1' : ''}" style="width: ${config.layoutStyle === 'modern' || config.layoutStyle === 'magazine' || config.layoutStyle === 'showcase' ? '100%' : `${config.layout.imageWidth}%`}; object-fit: cover;" alt="Feature">` : ''}
        </div>
      `;

      return `
      <main id="services" class="max-w-4xl mx-auto px-6 py-12 space-y-${config.layout.spacing * 4} ${config.layoutStyle === 'magazine' ? 'max-w-6xl' : ''}">
        ${section1}
        ${section2}
      </main>`;
  };

  const getFooterHtml = () => {
      let footerBg = `background-color: ${config.colors.primary}; color: white;`;
      if (config.layoutStyle === 'minimal') footerBg = `background-color: white; color: ${config.colors.text}; border-top: 1px solid #eee;`;
      if (config.layoutStyle === 'bold') footerBg = `background-color: black; color: white; border-top: 4px solid black;`;
      if (config.layoutStyle === 'magazine') footerBg = `background-color: white; color: black; border-top: 2px solid black;`;
      if (config.layoutStyle === 'showcase') footerBg = `background-color: black; color: white;`;

      const socialLinks = [];
      if (config.contact.facebook) socialLinks.push(`<a href="${config.contact.facebook}" target="_blank" class="hover:opacity-100 hover:underline">Facebook</a>`);
      if (config.contact.instagram) socialLinks.push(`<a href="${config.contact.instagram}" target="_blank" class="hover:opacity-100 hover:underline">Instagram</a>`);
      if (config.contact.twitter) socialLinks.push(`<a href="${config.contact.twitter}" target="_blank" class="hover:opacity-100 hover:underline">Twitter/X</a>`);
      if (config.contact.linkedin) socialLinks.push(`<a href="${config.contact.linkedin}" target="_blank" class="hover:opacity-100 hover:underline">LinkedIn</a>`);
      if (config.contact.youtube) socialLinks.push(`<a href="${config.contact.youtube}" target="_blank" class="hover:opacity-100 hover:underline">YouTube</a>`);
      if (config.contact.tiktok) socialLinks.push(`<a href="${config.contact.tiktok}" target="_blank" class="hover:opacity-100 hover:underline">TikTok</a>`);
      if (config.contact.whatsapp) socialLinks.push(`<a href="${config.contact.whatsapp}" target="_blank" class="hover:opacity-100 hover:underline">WhatsApp</a>`);

      return `
      <footer id="contact" style="${footerBg}" class="py-12 px-6">
        <div class="max-w-4xl mx-auto grid md:grid-cols-2 gap-8">
            <div>
                <h3 class="text-xl font-bold mb-4">Contact Us</h3>
                <ul class="space-y-3 mb-6 opacity-90">
                    ${config.contact.address ? `<li class="flex items-start">📍 ${config.contact.address}</li>` : ''}
                    ${config.contact.email ? `
                    <li>
                        ✉️ <a href="mailto:${config.contact.email}" ${config.features.contactForm ? 'onclick="openModal(event)"' : ''} class="hover:underline">${config.contact.email}</a>
                    </li>` : ''}
                    ${config.contact.phone ? `<li>📞 <a href="tel:${config.contact.phone}" class="hover:underline">${config.contact.phone}</a></li>` : ''}
                </ul>

                ${config.contact.address && config.features.showMap ? `
                <div class="w-full overflow-hidden ${config.layoutStyle === 'bold' ? 'border-4 border-white' : 'rounded-lg shadow-lg border border-white/20'}" style="height: ${config.layout.mapHeight}px">
                    <iframe 
                        width="100%" 
                        height="100%" 
                        frameborder="0" 
                        scrolling="no" 
                        marginheight="0" 
                        marginwidth="0" 
                        src="https://maps.google.com/maps?q=${encodeURIComponent(config.contact.address)}&t=&z=13&ie=UTF8&iwloc=&output=embed">
                    </iframe>
                </div>
                ` : ''}
            </div>
            <div>
                <h3 class="text-xl font-bold mb-4">Connect</h3>
                <div class="flex flex-wrap gap-4 mb-6 opacity-90">
                     ${socialLinks.join(' ')}
                </div>
                ${config.features.privacyPolicy ? `<p class="text-xs opacity-50"><a href="#" class="underline">Privacy Policy</a> &copy; ${new Date().getFullYear()} ${config.businessName}</p>` : ''}
            </div>
        </div>
      </footer>`;
  };

  // SEO Keyword Generation
  const keywords = [
      config.businessName, 
      config.businessType, 
      `${config.businessType} services`, 
      'small business', 
      'professional', 
      config.contact.address ? 'local' : '',
      config.contact.address ? config.contact.address.split(',').pop()?.trim() : ''
  ].filter(Boolean).join(', ');

  const escapedDescription = config.description.replace(/"/g, '&quot;');
  const escapedTitle = config.title.replace(/"/g, '&quot;');
  const escapedBusinessName = config.businessName.replace(/"/g, '&quot;');
  
  // Determine OG Image (use hero or fallback)
  // Note: Social platforms require a real URL for images to work perfectly, 
  // but embedded base64 is provided here as a placeholder for when the site is hosted.
  // Most crawlers ignore base64 in og:image, but it's good for completeness in this generator context.
  const ogImage = config.images.hero || ''; 

  // Construct HTML
  const htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>${config.businessName} | ${config.businessType}</title>
    
    ${config.images.favicon ? `<link rel="icon" href="${config.images.favicon}">` : ''}

    <!-- SEO Meta Tags -->
    <meta name="description" content="${escapedDescription}">
    <meta name="keywords" content="${keywords}">
    <meta name="author" content="${escapedBusinessName}">
    <meta name="robots" content="index, follow">
    
    <!-- Open Graph / Facebook -->
    <meta property="og:type" content="website">
    <meta property="og:title" content="${escapedTitle}">
    <meta property="og:description" content="${escapedDescription}">
    <meta property="og:site_name" content="${escapedBusinessName}">
    ${ogImage ? `<meta property="og:image" content="images/hero.jpg">` : ''}
    
    <!-- Twitter -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="${escapedTitle}">
    <meta name="twitter:description" content="${escapedDescription}">
    ${ogImage ? `<meta name="twitter:image" content="images/hero.jpg">` : ''}

    <script src="https://cdn.tailwindcss.com"></script>
    <link href="${getFontUrl(selectedFont.header)}" rel="stylesheet">
    <link href="${getFontUrl(selectedFont.body)}" rel="stylesheet">
    <style>
        html { scroll-behavior: smooth; scroll-padding-top: 80px; }
        body { font-family: '${selectedFont.body}', sans-serif; background-color: ${config.colors.background}; color: ${config.colors.text}; }
        h1, h2, h3, h4, h5, h6 { font-family: '${selectedFont.header}', serif; }
        .primary-bg { background-color: ${config.colors.primary}; }
        .accent-bg { background-color: ${config.colors.accent}; }
        .accent-text { color: ${config.colors.accent}; }
        ${modalCss}
    </style>
</head>
<body>
    ${getHeaderHtml()}
    ${getHeroHtml()}
    ${getMainContentHtml()}
    ${getFooterHtml()}
    
    ${config.features.cookieBanner ? `
    <div id="cookie-banner" class="fixed bottom-0 left-0 right-0 bg-gray-900 text-white p-4 text-center text-sm z-50">
        We use cookies to improve your experience. 
        <button onclick="document.getElementById('cookie-banner').remove()" class="ml-4 underline font-bold">OK</button>
    </div>` : ''}

    ${modalHtml}
</body>
</html>
  `;

  zip.file("index.html", htmlContent);
  
  const imgFolder = zip.folder("images");
  imgFolder?.file("readme.txt", "Images are currently embedded directly in the HTML for ease of sharing. In a production version, they would be saved here.");
  
  // If we have a hero image and want better SEO support in the zip, we try to save it as a file too
  if (config.images.hero) {
      const heroData = config.images.hero.split(',')[1];
      if (heroData) imgFolder?.file("hero.jpg", heroData, {base64: true});
  }
  
  // Save favicon (optional now that we use base64 in HTML, but kept for completeness if user wants the file)
  if (config.images.favicon) {
      const iconData = config.images.favicon.split(',')[1];
      if (iconData) imgFolder?.file("favicon.png", iconData, {base64: true});
  }

  return await zip.generateAsync({ type: "blob" });
};