import { createServer } from 'http';
import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
import { join, extname } from 'path';
import { launch } from 'puppeteer';

const DIST_DIR = join(import.meta.dirname, '..', 'dist');
const INDEX_PATH = join(DIST_DIR, 'index.html');

const MIME_TYPES = {
  '.html': 'text/html',
  '.js': 'application/javascript',
  '.css': 'text/css',
  '.json': 'application/json',
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.svg': 'image/svg+xml',
};

function startServer() {
  return new Promise((resolve) => {
    const server = createServer((req, res) => {
      const url = new URL(req.url, 'http://localhost');
      let filePath = join(DIST_DIR, url.pathname === '/' ? 'index.html' : url.pathname);

      if (!existsSync(filePath) || !statSync(filePath).isFile()) {
        // SPA fallback
        filePath = INDEX_PATH;
      }

      const ext = extname(filePath);
      const mime = MIME_TYPES[ext] || 'application/octet-stream';
      const content = readFileSync(filePath);
      res.writeHead(200, { 'Content-Type': mime });
      res.end(content);
    });

    server.listen(0, '127.0.0.1', () => {
      const port = server.address().port;
      resolve({ server, port });
    });
  });
}

async function prerender() {
  console.log('Starting prerender...');

  const { server, port } = await startServer();
  console.log(`Static server on port ${port}`);

  const browser = await launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox'],
  });

  try {
    const page = await browser.newPage();

    // Intercept API requests to prevent real fetches and retry loops
    await page.setRequestInterception(true);
    page.on('request', (req) => {
      const url = req.url();
      if (url.includes('/api/features')) {
        req.respond({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({ groups: [] }),
        });
      } else if (url.includes('/api/poi-categories')) {
        req.respond({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({ groups: [] }),
        });
      } else if (url.includes('/api/')) {
        req.respond({
          status: 200,
          contentType: 'application/json',
          body: '{}',
        });
      } else {
        req.continue();
      }
    });

    await page.goto(`http://127.0.0.1:${port}/`, {
      waitUntil: 'networkidle0',
      timeout: 30000,
    });

    // Wait for the home page heading to render
    await page.waitForSelector('h1', { timeout: 10000 });

    // Extract and clean the rendered HTML
    const html = await page.evaluate(() => {
      const root = document.getElementById('root');
      if (!root) return '';

      // Strip fade-in-visible classes (added by IntersectionObserver effects)
      root.querySelectorAll('.fade-in-visible').forEach((el) => {
        el.classList.remove('fade-in-visible');
      });

      // Clean canvas elements (dimensions set by ResizeObserver effect)
      root.querySelectorAll('canvas').forEach((canvas) => {
        canvas.removeAttribute('width');
        canvas.removeAttribute('height');
        canvas.style.removeProperty('width');
        canvas.style.removeProperty('height');
      });

      return root.innerHTML;
    });

    if (!html || html.length < 100) {
      throw new Error('Prerender produced too little HTML — something went wrong');
    }

    // Inject into dist/index.html
    const indexHtml = readFileSync(INDEX_PATH, 'utf-8');
    const updated = indexHtml.replace(
      '<div id="root"></div>',
      `<div id="root">${html}</div>`
    );

    if (updated === indexHtml) {
      throw new Error('Could not find <div id="root"></div> in index.html');
    }

    writeFileSync(INDEX_PATH, updated);
    console.log(`Prerendered ${html.length} chars into dist/index.html`);
  } finally {
    await browser.close();
    server.close();
  }
}

prerender().catch((err) => {
  console.error('Prerender failed:', err);
  process.exit(1);
});
