const fs = require("fs");
const path = require("path");
const React = require("react");
const ReactDOMServer = require("react-dom/server");
const { StaticRouter } = require("react-router");
const { CacheProvider } = require("@emotion/react");
const { ThemeProvider } = require("@mui/material/styles");
const createEmotionCache = require("../createEmotionCache.js").default;
const theme = require("../src/theme.js").default;
const createEmotionServer = require("@emotion/server/create-instance").default;

const renderPage = (
  component,
  location,
  filename,
  description,
  metaTags = "",
  needsRouter = false,
  config,
  suppressLogs = false,
  productData = null
) => {
  const {
    isProduction,
    outputDir,
    globalCss,
    globalCssCollection,
    webpackEntrypoints,
  } = config;
  const { optimizeCss } = require("./utils.cjs");

  // @note Set prerender fallback flag in global environment for CategoryBox during SSR
  if (typeof global !== "undefined" && global.window) {
    global.window.__PRERENDER_FALLBACK__ = {
      path: location,
      timestamp: Date.now()
    };
  }

  // Create fresh Emotion cache for each page
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  const wrappedComponent = needsRouter
    ? React.createElement(StaticRouter, { location: location }, component)
    : component;

  const pageElement = React.createElement(
    CacheProvider,
    { value: cache },
    React.createElement(ThemeProvider, { theme: theme }, wrappedComponent)
  );

  let renderedMarkup;
  let pageSpecificCss = ""; // Declare outside try block for broader scope

  try {
    renderedMarkup = ReactDOMServer.renderToString(pageElement);
    const emotionChunks = extractCriticalToChunks(renderedMarkup);

    // Collect CSS from this page for direct inlining (no global accumulation)
    if (emotionChunks.styles.length > 0) {
      emotionChunks.styles.forEach((style) => {
        if (style.css) {
          pageSpecificCss += style.css + "\n";
        }
      });
      if (!suppressLogs) console.log(`   - CSS rules: ${emotionChunks.styles.length}`);
    }
  } catch (error) {
    console.error(`❌ Rendering failed for ${filename}:`, error);
    return false;
  }

  // Use appropriate template path based on mode
  // In production, use a clean template file, not the already-rendered index.html
  const templatePath = isProduction
    ? path.resolve(__dirname, "..", "dist", "index_template.html")
    : path.resolve(__dirname, "..", "public", "index.html");
  let template = fs.readFileSync(templatePath, "utf8");

  // Build CSS and JS tags with optimized CSS loading
  let additionalTags = "";
  let inlinedCss = "";

  if (isProduction) {
    // Check if scripts are already present in template to avoid duplication
    const existingScripts =
      template.match(/<script[^>]*src="([^"]*)"[^>]*><\/script>/g) || [];
    const existingScriptSrcs = existingScripts
      .map((script) => {
        const match = script.match(/src="([^"]*)"/);
        return match ? match[1] : null;
      })
      .filter(Boolean);

    // OPTIMIZATION: Inline critical CSS instead of loading externally
    // Read and inline webpack CSS files to eliminate render-blocking requests
    webpackEntrypoints.css.forEach((cssFile) => {
      if (!template.includes(`href="${cssFile}"`)) {
        try {
          const cssPath = path.resolve(__dirname, "..", "dist", cssFile.replace(/^\//, ""));
          if (fs.existsSync(cssPath)) {
            const cssContent = fs.readFileSync(cssPath, "utf8");
            // Use advanced CSS optimization
            const optimizedCss = optimizeCss(cssContent);
            inlinedCss += optimizedCss;
            if (!suppressLogs) console.log(`   ✅ Inlined CSS: ${cssFile} (${Math.round(optimizedCss.length / 1024)}KB)`);
          } else {
            // Fallback to external loading if file not found
            additionalTags += `<link rel="preload" href="${cssFile}" as="style" onload="this.onload=null;this.rel='stylesheet'">`;
            additionalTags += `<noscript><link rel="stylesheet" href="${cssFile}"></noscript>`;
            if (!suppressLogs) console.log(`   ⚠️ CSS file not found for inlining: ${cssPath}, using async loading`);
          }
        } catch (error) {
          // Fallback to external loading if reading fails
          additionalTags += `<link rel="preload" href="${cssFile}" as="style" onload="this.onload=null;this.rel='stylesheet'">`;
          additionalTags += `<noscript><link rel="stylesheet" href="${cssFile}"></noscript>`;
          if (!suppressLogs) console.log(`   ⚠️ Error reading CSS file ${cssFile}: ${error.message}, using async loading`);
        }
      }
    });

    // Inline page-specific CSS directly (no shared prerender.css file)
    if (pageSpecificCss.trim()) {
      // Use advanced CSS optimization on page-specific CSS
      const optimizedPageCss = optimizeCss(pageSpecificCss);
      inlinedCss += optimizedPageCss;
      if (!suppressLogs) console.log(`   ✅ Inlined page-specific CSS (${Math.round(optimizedPageCss.length / 1024)}KB)`);
    }

    // Add JavaScript files
    webpackEntrypoints.js.forEach((jsFile) => {
      if (!existingScriptSrcs.includes(jsFile)) {
        additionalTags += `<script src="${jsFile}"></script>`;
      }
    });
  } else {
    // In development, try to inline prerender CSS as well
    try {
      const prerenderCssPath = path.resolve(__dirname, "..", outputDir, "prerender.css");
             if (fs.existsSync(prerenderCssPath)) {
         const prerenderCssContent = fs.readFileSync(prerenderCssPath, "utf8");
         const optimizedCss = optimizeCss(prerenderCssContent);
         inlinedCss += optimizedCss;
         if (!suppressLogs) console.log(`   ✅ Inlined prerender CSS in development (${Math.round(optimizedCss.length / 1024)}KB)`);
       } else {
        // Fallback to external loading
        additionalTags += `<link rel="stylesheet" href="/prerender.css">`;
      }
    } catch (error) {
      // Fallback to external loading
      additionalTags += `<link rel="stylesheet" href="/prerender.css">`;
    }
  }

  // Create script to save prerendered content to window object for fallback use
  const prerenderFallbackScript = `
    <script>
      // Save prerendered content to window object for SocketProvider fallback
            window.__PRERENDER_FALLBACK__ = {
        path: '${location}',
        content: ${JSON.stringify(renderedMarkup)},
        timestamp: ${Date.now()}
      };
      
      // DEBUG: Multiple alerts throughout the loading process
      // Debug alerts removed
      
      
    </script>
  `;

  // @note Create script to populate window.productCache with ONLY the static category tree
  let productCacheScript = '';
  if (typeof global !== "undefined" && global.window && global.window.categoryCache) {
    // Only include the static categoryTree_209, not any dynamic data that gets added during rendering
    const staticCache = {};
    if (global.window.categoryCache["209_de"]) {
      staticCache["209_de"] = global.window.categoryCache["209_de"];
    }
    
    const staticCacheData = JSON.stringify(staticCache);
    productCacheScript = `
    <script>
      // Populate window.categoryCache with static category tree only
      window.categoryCache = ${staticCacheData};
    </script>
    `;
  }

  // Create script to populate window.productDetailCache for individual product pages
  let productDetailCacheScript = '';
  if (productData && productData.product) {
    // Cache the entire response object (includes product, attributes, etc.)
    // Use language-aware cache key (prerender defaults to German)
    const productDetailCacheData = JSON.stringify(productData);
    const language = 'de'; // Prerender system caches German version
    const cacheKey = `product_${productData.product.seoName}_${language}`;
    productDetailCacheScript = `
    <script>
      // Populate window.productDetailCache with complete product data for SPA hydration
      if (!window.productDetailCache) {
        window.productDetailCache = {};
      }
      window.productDetailCache['${cacheKey}'] = ${productDetailCacheData};
    </script>
    `;
  }

  // Combine all CSS (global + inlined) into a single optimized style tag
  const combinedCss = globalCss + (inlinedCss ? '\n' + inlinedCss : '');
  const combinedCssTag = combinedCss ? `<style type="text/css">${combinedCss}</style>` : '';
  
  // Add resource hints for better performance
  const resourceHints = `
    <meta name="viewport" content="width=device-width, initial-scale=1">
  `;
  
  template = template.replace(
    "</head>",
    `${resourceHints}${combinedCssTag}${additionalTags}${metaTags}${prerenderFallbackScript}${productCacheScript}${productDetailCacheScript}</head>`
  );

  const rootDivRegex = /<div id="root"[\s\S]*?>[\s\S]*?<\/div>/;
  const replacementHtml = `<div id="root">${renderedMarkup}</div>`;

  let newHtml;
  if (rootDivRegex.test(template)) {
    if (!suppressLogs) console.log(`   📝 Root div found, replacing with ${renderedMarkup.length} chars of markup`);
    newHtml = template.replace(rootDivRegex, replacementHtml);
  } else {
    if (!suppressLogs) console.log(`   ⚠️ No root div found, appending to body`);
    newHtml = template.replace("<body>", `<body>${replacementHtml}`);
  }

  const outputPath = path.resolve(__dirname, "..", outputDir, filename);

  // Ensure directory exists for nested paths
  const outputDirPath = path.dirname(outputPath);
  if (!fs.existsSync(outputDirPath)) {
    fs.mkdirSync(outputDirPath, { recursive: true });
  }

  fs.writeFileSync(outputPath, newHtml);

  if (!suppressLogs) {
    console.log(`✅ ${description} prerendered to ${outputPath}`);
    console.log(`   - Markup length: ${renderedMarkup.length} characters`);
    if (productDetailCacheScript) {
      console.log(`   - Product detail cache populated for SPA hydration`);
    }
  }

  return true;
};

module.exports = {
  renderPage,
};
