require("@babel/register")({
  presets: [
    ["@babel/preset-env", { targets: { node: "current" } }],
    "@babel/preset-react",
  ],
  extensions: [".js", ".jsx"],
  ignore: [/node_modules/],
});

// Minimal globals for socket.io-client only - no JSDOM to avoid interference
global.window = {}; // Minimal window object for productCache
global.navigator = { userAgent: "node.js" };
// Use Node.js URL constructor for React Router compatibility
global.URL = require("url").URL;
global.Blob = class MockBlob {
  constructor(data, options) {
    this.data = data;
    this.type = options?.type || "";
  }
};

class CategoryService {
  constructor() {
    this.get = this.get.bind(this);
  }

  getSync(categoryId, language = "de") {
    const cacheKey = `${categoryId}_${language}`;
    return null;
  }

  async get(categoryId, language = "de") {
    const cacheKey = `${categoryId}_${language}`;
    return null;
  }
}
global.window.categoryService = new CategoryService();


// Import modules
const fs = require("fs");
const path = require("path");
const React = require("react");
const io = require("socket.io-client");
const os = require("os");
const { Worker, isMainThread, parentPort, workerData } = require("worker_threads");

// Initialize i18n for prerendering with German as default
const i18n = require("i18next");
const { initReactI18next } = require("react-i18next");

// Import all translation files
const translationDE = require("./src/i18n/locales/de/translation.js").default;
const translationEN = require("./src/i18n/locales/en/translation.js").default;
const translationAR = require("./src/i18n/locales/ar/translation.js").default;
const translationBG = require("./src/i18n/locales/bg/translation.js").default;
const translationCS = require("./src/i18n/locales/cs/translation.js").default;
const translationEL = require("./src/i18n/locales/el/translation.js").default;
const translationES = require("./src/i18n/locales/es/translation.js").default;
const translationFR = require("./src/i18n/locales/fr/translation.js").default;
const translationHR = require("./src/i18n/locales/hr/translation.js").default;
const translationHU = require("./src/i18n/locales/hu/translation.js").default;
const translationIT = require("./src/i18n/locales/it/translation.js").default;
const translationPL = require("./src/i18n/locales/pl/translation.js").default;
const translationRO = require("./src/i18n/locales/ro/translation.js").default;
const translationRU = require("./src/i18n/locales/ru/translation.js").default;
const translationSK = require("./src/i18n/locales/sk/translation.js").default;
const translationSL = require("./src/i18n/locales/sl/translation.js").default;
const translationSR = require("./src/i18n/locales/sr/translation.js").default;
const translationSV = require("./src/i18n/locales/sv/translation.js").default;
const translationTR = require("./src/i18n/locales/tr/translation.js").default;
const translationUK = require("./src/i18n/locales/uk/translation.js").default;
const translationZH = require("./src/i18n/locales/zh/translation.js").default;

// Initialize i18n for prerendering
i18n
  .use(initReactI18next)
  .init({
    resources: {
      de: { translation: translationDE },
      en: { translation: translationEN },
      ar: { translation: translationAR },
      bg: { translation: translationBG },
      cs: { translation: translationCS },
      el: { translation: translationEL },
      es: { translation: translationES },
      fr: { translation: translationFR },
      hr: { translation: translationHR },
      hu: { translation: translationHU },
      it: { translation: translationIT },
      pl: { translation: translationPL },
      ro: { translation: translationRO },
      ru: { translation: translationRU },
      sk: { translation: translationSK },
      sl: { translation: translationSL },
      sr: { translation: translationSR },
      sv: { translation: translationSV },
      tr: { translation: translationTR },
      uk: { translation: translationUK },
      zh: { translation: translationZH }
    },
    lng: 'de', // Default to German for prerendering
    fallbackLng: 'de',
    debug: false,
    interpolation: {
      escapeValue: false
    },
    react: {
      useSuspense: false
    }
  });

// Make i18n available globally for components
global.i18n = i18n;

// Import split modules
const config = require("./prerender/config.cjs");

// Import shop config - using require with Babel transpilation
const shopConfig = require("./src/config.js").default;
const { renderPage } = require("./prerender/renderer.cjs");
const {
  collectAllCategories,
} = require("./prerender/utils.cjs");
const {
  generateProductMetaTags,
  generateProductJsonLd,
  generateCategoryMetaTags,
  generateCategoryJsonLd,
  generateHomepageMetaTags,
  generateHomepageJsonLd,
  generateSitemapJsonLd,
  generateKonfiguratorMetaTags,
  generateXmlSitemap,
  generateRobotsTxt,
  generateProductsXml,
  generateLlmsTxt,
  generateCategoryLlmsTxt,
  generateAllCategoryLlmsPages,
  generateCategoryProductList,
} = require("./prerender/seo.cjs");
const {
  fetchCategoryProducts,
  fetchProductDetails,
  saveProductImages,
  saveCategoryImages,
} = require("./prerender/data-fetching.cjs");

// Import components
const PrerenderCategory = require("./src/PrerenderCategory.js").default;
const PrerenderProduct = require("./src/PrerenderProduct.js").default;
const PrerenderKonfigurator = require("./src/PrerenderKonfigurator.js").default;
const PrerenderProfile = require("./src/PrerenderProfile.js").default;

// Import static page components
const Datenschutz = require("./src/pages/Datenschutz.js").default;
const Impressum = require("./src/pages/Impressum.js").default;
const Batteriegesetzhinweise =
  require("./src/pages/Batteriegesetzhinweise.js").default;
const Widerrufsrecht = require("./src/pages/Widerrufsrecht.js").default;
const Sitemap = require("./src/pages/Sitemap.js").default;
const PrerenderSitemap = require("./src/PrerenderSitemap.js").default;
const PrerenderCategoriesPage = require("./src/PrerenderCategoriesPage.js").default;
const AGB = require("./src/pages/AGB.js").default;
const NotFound404 = require("./src/pages/NotFound404.js").default;

// Worker function for parallel product rendering  
const renderProductWorker = async (productSeoNames, workerId, progressCallback, categoryMap = {}) => {
  const socketUrl = "http://127.0.0.1:9303";
  const workerSocket = io(socketUrl, config.socketIoClientOptions);

  return new Promise((resolve) => {
    let processedCount = 0;
    let successCount = 0;
    const results = [];

    const processNextProduct = async () => {
      if (processedCount >= productSeoNames.length) {
        workerSocket.disconnect();
        resolve({ successCount, results, workerId });
        return;
      }

      const productSeoName = productSeoNames[processedCount];
      processedCount++;

      try {
        const productDetails = await fetchProductDetails(workerSocket, productSeoName);

        const actualSeoName = productDetails.product.seoName || productSeoName;
        const productComponent = React.createElement(PrerenderProduct, {
          productData: productDetails,
          t: global.i18n.t.bind(global.i18n),
        });

        const filename = `Artikel/${actualSeoName}`;
        const location = `/Artikel/${actualSeoName}`;
        const description = `Product "${productDetails.product.name}" (seoName: ${productSeoName})`;
        const metaTags = generateProductMetaTags({
          ...productDetails.product,
          seoName: actualSeoName,
        }, shopConfig.baseUrl, shopConfig);
        // Get category info from categoryMap if available
        const categoryInfo = productDetails.product.categoryId ? categoryMap[productDetails.product.categoryId] : null;

        const jsonLdScript = generateProductJsonLd({
          ...productDetails.product,
          seoName: actualSeoName,
        }, shopConfig.baseUrl, shopConfig, categoryInfo);
        const combinedMetaTags = metaTags + "\n" + jsonLdScript;

        const success = renderPage(
          productComponent,
          location,
          filename,
          description,
          combinedMetaTags,
          true,
          config,
          true, // Suppress logs during parallel rendering to avoid interfering with progress bar
          productDetails // Pass product data for cache population
        );

        if (success) {
          successCount++;
        }

        const result = {
          productSeoName,
          productName: productDetails.product.name,
          success,
          workerId
        };

        results.push(result);

        // Call progress callback if provided
        if (progressCallback) {
          progressCallback(result);
        }

        // Small delay to avoid overwhelming the server
        setTimeout(processNextProduct, 25);
      } catch (error) {
        const result = {
          productSeoName,
          productName: productSeoName,
          success: false,
          error: error.message,
          workerId
        };

        results.push(result);

        // Call progress callback if provided
        if (progressCallback) {
          progressCallback(result);
        }

        setTimeout(processNextProduct, 25);
      }
    };

    workerSocket.on("connect", () => {
      processNextProduct();
    });

    workerSocket.on("connect_error", (err) => {
      console.error(`Worker ${workerId} socket connection error:`, err);
      resolve({ successCount: 0, results: [], workerId });
    });
  });
};

// Function to render products in parallel
const renderProductsInParallel = async (allProductsArray, maxWorkers, totalProducts, categoryMap = {}) => {
  // Shared progress tracking
  let completedProducts = 0;
  let totalSuccessCount = 0;
  let lastProductName = '';
  const progressResults = [];
  const workerCounts = new Array(maxWorkers).fill(0); // Track per-worker progress
  const workerSuccess = new Array(maxWorkers).fill(0); // Track per-worker success count

  // Helper function to display progress bar with worker stats
  const updateProgressBar = (current, total, productName = '') => {
    const percentage = Math.round((current / total) * 100);
    const barLength = 30;
    const filledLength = Math.round((barLength * current) / total);
    const bar = '█'.repeat(filledLength) + '░'.repeat(barLength - filledLength);

    // @note Single line progress update to prevent flickering
    const truncatedName = productName ? ` - ${productName.substring(0, 25)}${productName.length > 25 ? '...' : ''}` : '';

    // Build worker stats on one line
    let workerStats = '';
    for (let i = 0; i < Math.min(maxWorkers, 8); i++) { // Limit to 8 workers to fit on screen
      workerStats += `W${i + 1}:${workerCounts[i]}/${workerSuccess[i]} `;
    }

    // Single line update without complex cursor movements
    process.stdout.write(`\r   [${bar}] ${percentage}% (${current}/${total})${truncatedName}\n   ${workerStats}${current < total ? '\x1b[1A' : '\n'}`);
  };

  // Split products among workers
  const productsPerWorker = Math.ceil(allProductsArray.length / maxWorkers);
  const workerPromises = [];

  // Initial progress bar
  updateProgressBar(0, totalProducts);

  for (let i = 0; i < maxWorkers; i++) {
    const start = i * productsPerWorker;
    const end = Math.min(start + productsPerWorker, allProductsArray.length);
    const productsForWorker = allProductsArray.slice(start, end);

    if (productsForWorker.length > 0) {
      const promise = renderProductWorker(productsForWorker, i + 1, (result) => {
        // Progress callback - called each time a product is completed
        completedProducts++;
        progressResults.push(result);
        lastProductName = result.productName;

        // Update per-worker counters
        const workerIndex = result.workerId - 1; // Convert to 0-based index
        workerCounts[workerIndex]++;

        if (result.success) {
          totalSuccessCount++;
          workerSuccess[workerIndex]++;
        } else if (result.error) {
          // Don't log errors immediately to avoid interfering with progress bar
          // Errors will be shown after completion
        }

        // Update progress bar with worker stats
        updateProgressBar(completedProducts, totalProducts, lastProductName);
      }, categoryMap);

      workerPromises.push(promise);
    }
  }

  try {
    // Wait for all workers to complete
    await Promise.all(workerPromises);

    // Ensure final progress update
    updateProgressBar(totalProducts, totalProducts, lastProductName);

    // Show any errors that occurred
    const errorResults = progressResults.filter(r => !r.success && r.error);
    if (errorResults.length > 0) {
      console.log(`\n❌ ${errorResults.length} products failed to render:`);
      errorResults.forEach(result => {
        console.log(`   - ${result.productSeoName}: ${result.error}`);
      });
    }

    return totalSuccessCount;
  } catch (error) {
    console.error('Error in parallel rendering:', error);
    return totalSuccessCount; // Return what we managed to complete
  }
};

const renderApp = async (categoryData, socket) => {
  if (categoryData) {
    global.window.categoryCache = {
      "209_de": categoryData,
    };
    // @note Make cache available to components during rendering
    global.categoryCache = global.window.categoryCache;
  } else {
    global.window.categoryCache = {};
    global.categoryCache = {};
  }

  // Helper to call renderPage with config
  const render = (
    component,
    location,
    filename,
    description,
    metaTags = "",
    needsRouter = false
  ) => {
    return renderPage(
      component,
      location,
      filename,
      description,
      metaTags,
      needsRouter,
      config
    );
  };

  console.log("🏠 Rendering home page...");
  const PrerenderHome = require("./src/PrerenderHome.js").default;
  const homeComponent = React.createElement(PrerenderHome, null);
  const homeFilename = config.isProduction
    ? "index.html"
    : "index.prerender.html";
  const homeMetaTags = generateHomepageMetaTags(shopConfig.baseUrl, shopConfig);
  const homepageCategories = categoryData ? collectAllCategories(categoryData) : [];
  const homeJsonLd = generateHomepageJsonLd(shopConfig.baseUrl, shopConfig, homepageCategories);
  const combinedHomeMeta = homeMetaTags + "\n" + homeJsonLd;
  const homeSuccess = render(
    homeComponent,
    "/",
    homeFilename,
    "Home page",
    combinedHomeMeta,
    true
  );

  if (!homeSuccess) {
    process.exit(1);
  }

  // Copy index.html to resetPassword (no file extension) for SPA routing
  if (config.isProduction) {
    const indexPath = path.resolve(__dirname, config.outputDir, "index.html");
    const resetPasswordPath = path.resolve(__dirname, config.outputDir, "resetPassword");
    fs.copyFileSync(indexPath, resetPasswordPath);
    console.log(`✅ Copied index.html to ${resetPasswordPath}`);

    // Copy index.html to linkTelegram (no file extension) for SPA routing
    const linkTelegramPath = path.resolve(__dirname, config.outputDir, "linkTelegram");
    fs.copyFileSync(indexPath, linkTelegramPath);
    console.log(`✅ Copied index.html to ${linkTelegramPath}`);
  }

  // Render static pages
  console.log("\n📄 Rendering static pages...");

  const staticPages = [
    {
      component: Datenschutz,
      path: "/datenschutz",
      filename: "datenschutz",
      description: "Datenschutz page",
    },
    {
      component: Impressum,
      path: "/impressum",
      filename: "impressum",
      description: "Impressum page",
    },
    {
      component: Batteriegesetzhinweise,
      path: "/batteriegesetzhinweise",
      filename: "batteriegesetzhinweise",
      description: "Batteriegesetzhinweise page",
    },
    {
      component: Widerrufsrecht,
      path: "/widerrufsrecht",
      filename: "widerrufsrecht",
      description: "Widerrufsrecht page",
    },
    {
      component: PrerenderSitemap,
      path: "/sitemap",
      filename: "sitemap",
      description: "Sitemap page",
      needsCategoryData: true,
    },
    {
      component: PrerenderCategoriesPage,
      path: "/Kategorien",
      filename: "Kategorien",
      description: "Categories page",
      needsCategoryData: true,
    },
    { component: AGB, path: "/agb", filename: "agb", description: "AGB page" },
    { component: NotFound404, path: "/404", filename: "404", description: "404 Not Found page" },
    {
      component: PrerenderKonfigurator,
      path: "/Konfigurator",
      filename: "Konfigurator",
      description: "Growbox Konfigurator page",
    },
    {
      component: PrerenderProfile,
      path: "/profile",
      filename: "profile",
      description: "Profile page",
    },
  ];

  let staticPagesRendered = 0;
  for (const page of staticPages) {
    // Pass category data as props if needed
    const pageProps = page.needsCategoryData ? { categoryData } : null;
    const pageComponent = React.createElement(page.component, pageProps);
    let metaTags = "";

    // Special handling for Sitemap page to include category data
    if (page.filename === "sitemap" && categoryData) {
      const sitemapCategories = collectAllCategories(categoryData);
      metaTags = generateSitemapJsonLd(sitemapCategories, shopConfig.baseUrl, shopConfig);
    }

    // Special handling for Konfigurator page to include SEO tags
    if (page.filename === "Konfigurator") {
      const konfiguratorMetaTags = generateKonfiguratorMetaTags(shopConfig.baseUrl, shopConfig);
      metaTags = konfiguratorMetaTags;
    }

    const success = render(
      pageComponent,
      page.path,
      page.filename,
      page.description,
      metaTags,
      true
    );
    if (success) {
      staticPagesRendered++;
    }
  }

  console.log(
    `✅ Successfully rendered ${staticPagesRendered}/${staticPages.length} static pages!`
  );

  // Collect all products for product page generation
  const allProducts = new Set();
  const allProductsData = []; // @note Store full product data for products.xml generation

  // Generate category pages if we have category data
  if (categoryData && socket) {
    console.log("\n📂 Rendering category pages with product data...");
    const allCategories = collectAllCategories(categoryData);
    console.log(`Found ${allCategories.length} categories to render`);

    // First, collect category images for all categories
    console.log("\n📂 Collecting category images...");
    await saveCategoryImages(socket, allCategories, config.outputDir);

    let categoryPagesRendered = 0;
    let categoriesWithProducts = 0;

    const allCategoriesWithVirtual = [
      ...allCategories,
      {
        id: "neu",
        name: "Neuheiten",
        seoName: "neu",
        parentId: 209,
      },
      {
        id: "bald",
        name: "Demnächst",
        seoName: "bald",
        parentId: 209,
      },
    ];

    for (const category of allCategoriesWithVirtual) {
      // Skip categories without seoName
      if (!category.seoName) {
        console.log(
          `⚠️ Skipping category "${category.name}" (ID: ${category.id}) - no seoName`
        );
        continue;
      }

      try {
        console.log(
          `\n🔍 Fetching products for category "${category.name}" (ID: ${category.id})...`
        );

        let productData = null;
        try {
          productData = await fetchCategoryProducts(socket, category.id);
          console.log(
            `   ✅ Found ${productData.products ? productData.products.length : 0
            } products`
          );

          if (productData.products && productData.products.length > 0) {
            categoriesWithProducts++;

            // Collect products for individual page generation
            productData.products.forEach((product) => {
              if (product.seoName) {
                allProducts.add(product.seoName);
                // @note Store full product data for products.xml generation with category ID
                allProductsData.push({
                  ...product,
                  seoName: product.seoName,
                  categoryId: category.id // Add the category ID for Google Shopping category mapping
                });
              }
            });

            // Fetch and save product images
            await saveProductImages(
              socket,
              productData.products,
              category.name,
              config.outputDir
            );

            // Don't accumulate data in global cache - just use the data directly for this page
            // The global cache should only contain the static category tree
          }
        } catch (productError) {
          console.log(`   ⚠️ No products found: ${productError.message}`);
        }

        const categoryComponent = React.createElement(PrerenderCategory, {
          categoryId: category.id,
          categoryName: category.name,
          categorySeoName: category.seoName,
          productData: productData,
        });

        const filename = `Kategorie/${category.seoName}`;
        const location = `/Kategorie/${category.seoName}`;
        const description = `Category "${category.name}" (ID: ${category.id})`;
        const categoryMetaTags = generateCategoryMetaTags(
          category,
          shopConfig.baseUrl,
          shopConfig
        );
        const categoryJsonLd = generateCategoryJsonLd(
          category,
          productData?.products || [],
          shopConfig.baseUrl,
          shopConfig
        );
        const combinedCategoryHead = categoryMetaTags + "\n" + categoryJsonLd;

        const success = render(
          categoryComponent,
          location,
          filename,
          description,
          combinedCategoryHead,
          true
        );
        if (success) {
          categoryPagesRendered++;
        }

        // Small delay to avoid overwhelming the server
        await new Promise((resolve) => setTimeout(resolve, 100));
      } catch (error) {
        console.error(
          `❌ Failed to render category ${category.id} (${category.name}):`,
          error
        );
      }
    }

    console.log(
      `\n🎉 Successfully rendered ${categoryPagesRendered} category pages!`
    );
    console.log(`📦 ${categoriesWithProducts} categories had product data`);

    // Generate individual product pages
    if (allProducts.size > 0) {
      const totalProducts = allProducts.size;
      const numCPUs = os.cpus().length;
      const maxWorkers = Math.min(numCPUs, totalProducts, 8); // Cap at 8 workers to avoid overwhelming the server

      // Create category map for breadcrumbs
      const categoryMap = {};
      allCategories.forEach(category => {
        categoryMap[category.id] = {
          name: category.name,
          seoName: category.seoName
        };
      });

      console.log(
        `\n📦 Rendering ${totalProducts} individual product pages using ${maxWorkers} parallel workers...`
      );

      const productPagesRendered = await renderProductsInParallel(
        Array.from(allProducts),
        maxWorkers,
        totalProducts,
        categoryMap
      );

      console.log(
        `🎉 Successfully rendered ${productPagesRendered}/${totalProducts} product pages!`
      );
    }
  } else {
    console.log(
      "⚠️ No category data or socket available - skipping category page generation"
    );
  }

  // No longer writing combined CSS file - each page has its own embedded CSS

  // Generate XML sitemap with all rendered pages
  console.log("\n🗺️ Generating XML sitemap...");
  const allCategories = categoryData ? collectAllCategories(categoryData) : [];
  const allProductsArray = Array.from(allProducts);
  const xmlSitemap = generateXmlSitemap(allCategories, allProductsArray, shopConfig.baseUrl);

  const sitemapPath = path.resolve(__dirname, config.outputDir, "sitemap.xml");
  fs.writeFileSync(sitemapPath, xmlSitemap);

  console.log(`✅ XML sitemap generated: ${sitemapPath}`);
  console.log(`   - Homepage: 1 URL`);
  console.log(`   - Static pages: 6 URLs`);
  console.log(`   - Category pages: ${allCategories.length} URLs`);
  console.log(`   - Product pages: ${allProductsArray.length} URLs`);
  console.log(
    `   - Total URLs: ${1 + 6 + allCategories.length + allProductsArray.length}`
  );

  // Generate robots.txt
  console.log("\n🤖 Generating robots.txt...");
  const robotsTxtContent = generateRobotsTxt(shopConfig.baseUrl);
  const robotsTxtPath = path.resolve(__dirname, config.outputDir, "robots.txt");
  fs.writeFileSync(robotsTxtPath, robotsTxtContent);

  console.log(`✅ robots.txt generated: ${robotsTxtPath}`);
  console.log(`   - Allows all crawlers`);
  console.log(`   - References sitemap.xml`);
  console.log(`   - Includes crawl-delay directive`);

  // Generate products.xml (Google Shopping feed) in parallel to sitemap.xml
  if (allProductsData.length > 0) {
    console.log("\n🛒 Generating products.xml (Google Shopping feed)...");

    try {
      const productsXml = generateProductsXml(allProductsData, shopConfig.baseUrl, shopConfig);

      const productsXmlPath = path.resolve(__dirname, config.outputDir, "products.xml");

      // Write with explicit UTF-8 encoding
      fs.writeFileSync(productsXmlPath, productsXml, { encoding: 'utf8' });

      console.log(`✅ products.xml generated: ${productsXmlPath}`);
      console.log(`   - Products included: ${allProductsData.length}`);
      console.log(`   - Format: Google Shopping RSS 2.0 feed`);
      console.log(`   - Encoding: UTF-8`);
      console.log(`   - Includes: title, description, price, availability, images`);

      // Verify the file is valid UTF-8
      try {
        const verification = fs.readFileSync(productsXmlPath, 'utf8');
        console.log(`   - File verification: ✅ Valid UTF-8 (${Math.round(verification.length / 1024)}KB)`);
      } catch (verifyError) {
        console.log(`   - File verification: ⚠️ ${verifyError.message}`);
      }

      // Validate XML against Google Shopping schema
      try {
        const ProductsXmlValidator = require('./scripts/validate-products-xml.cjs');
        const validator = new ProductsXmlValidator(productsXmlPath);
        const validationResults = await validator.validate();

        if (validationResults.valid) {
          console.log(`   - Schema validation: ✅ Valid Google Shopping RSS 2.0`);
        } else {
          console.log(`   - Schema validation: ⚠️ ${validationResults.summary.errorCount} errors, ${validationResults.summary.warningCount} warnings`);

          // Show first few errors for quick debugging
          if (validationResults.errors.length > 0) {
            console.log(`   - First error: ${validationResults.errors[0].message}`);
          }
        }
      } catch (validationError) {
        console.log(`   - Schema validation: ⚠️ Validation failed: ${validationError.message}`);
      }

    } catch (error) {
      console.error(`❌ Error generating products.xml: ${error.message}`);
      console.log("\n⚠️  Skipping products.xml generation due to errors");
    }
  } else {
    console.log("\n⚠️  No product data available - skipping products.xml generation");
  }

  // Generate llms.txt (LLM-friendly markdown sitemap) and category-specific files
  console.log("\n🤖 Generating LLM sitemap files...");

  try {
    // Generate main llms.txt overview file
    const llmsTxt = generateLlmsTxt(allCategories, allProductsData, shopConfig.baseUrl, shopConfig);
    const llmsTxtPath = path.resolve(__dirname, config.outputDir, "llms.txt");
    fs.writeFileSync(llmsTxtPath, llmsTxt, { encoding: 'utf8' });

    console.log(`✅ Main llms.txt generated: ${llmsTxtPath}`);
    console.log(`   - Static pages: 8 pages`);
    console.log(`   - Categories: ${allCategories.length} with links to detailed files`);
    console.log(`   - File size: ${Math.round(llmsTxt.length / 1024)}KB`);

    // Group products by category for category-specific files
    const productsByCategory = {};
    allProductsData.forEach((product) => {
      const categoryId = product.categoryId || 'uncategorized';
      if (!productsByCategory[categoryId]) {
        productsByCategory[categoryId] = [];
      }
      productsByCategory[categoryId].push(product);
    });

    // Generate category-specific LLM files with pagination
    let categoryFilesGenerated = 0;
    let totalCategoryProducts = 0;
    let totalPaginatedFiles = 0;

    for (const category of allCategories) {
      if (category.seoName) {
        const categoryProducts = productsByCategory[category.id] || [];
        const categorySlug = category.seoName.toLowerCase().replace(/[^a-z0-9]/g, '-');

        // Generate all paginated files for this category
        const categoryPages = generateAllCategoryLlmsPages(category, categoryProducts, shopConfig.baseUrl, shopConfig);

        // Write each paginated file
        for (const page of categoryPages) {
          const pagePath = path.resolve(__dirname, config.outputDir, page.fileName);
          fs.writeFileSync(pagePath, page.content, { encoding: 'utf8' });
          totalPaginatedFiles++;
        }

        // Generate and write the product list file for this category
        const productList = generateCategoryProductList(category, categoryProducts);
        const listPath = path.resolve(__dirname, config.outputDir, productList.fileName);
        fs.writeFileSync(listPath, productList.content, { encoding: 'utf8' });

        const pageCount = categoryPages.length;
        const totalSize = categoryPages.reduce((sum, page) => sum + page.content.length, 0);

        console.log(`   ✅ llms-${categorySlug}-page-*.txt - ${categoryProducts.length} products across ${pageCount} pages (${Math.round(totalSize / 1024)}KB total)`);
        console.log(`   📋 ${productList.fileName} - ${productList.productCount} products (${Math.round(productList.content.length / 1024)}KB)`);

        categoryFilesGenerated++;
        totalCategoryProducts += categoryProducts.length;
      }
    }

    console.log(`   📄 Total paginated files generated: ${totalPaginatedFiles}`);
    console.log(`   📦 Total products across all categories: ${totalCategoryProducts}`);

    try {
      const verification = fs.readFileSync(llmsTxtPath, 'utf8');
      console.log(`   - File verification: ✅ All files valid UTF-8`);
    } catch (verifyError) {
      console.log(`   - File verification: ⚠️ ${verifyError.message}`);
    }

  } catch (error) {
    console.error(`❌ Error generating LLM sitemap files: ${error.message}`);
    console.log("\n⚠️  Skipping LLM sitemap generation due to errors");
  }
};

const fetchCategoryDataAndRender = () => {
  const socketUrl = "http://127.0.0.1:9303";
  console.log(`Connecting to socket at ${socketUrl} to fetch categories...`);

  const timeout = setTimeout(() => {
    console.error(
      "Error: Prerender script timed out after 15 seconds. Check backend connectivity."
    );
    process.exit(1);
  }, 15000);

  const socket = io(socketUrl, config.socketIoClientOptions);

  socket.on("connect", () => {
    console.log('Socket connected. Emitting "categoryList"...');
    socket.emit("categoryList", { categoryId: 209 }, async (response) => {
      clearTimeout(timeout);

      if (response && response.categoryTree) {
        console.log("Successfully fetched category data.");
        await renderApp(response.categoryTree, socket);
      } else {
        console.error("Error: Invalid category data received.", response);
        await renderApp(null, socket);
      }
      socket.disconnect();
    });
  });

  socket.on("connect_error", async (err) => {
    clearTimeout(timeout);
    console.error("Socket connection error:", err);
    await renderApp(null, null);
    socket.disconnect();
  });

  socket.on("error", async (err) => {
    clearTimeout(timeout);
    console.error("Socket error:", err);
    await renderApp(null, null);
    socket.disconnect();
  });

  socket.on("disconnect", (reason) => {
    console.log(`Socket disconnected: ${reason}`);
    clearTimeout(timeout);
  });
};

fetchCategoryDataAndRender();
