import fs from 'node:fs';
import path from 'node:path';
import http from 'node:http';
import { fileURLToPath } from 'node:url';
import express from 'express';
import puppeteer from 'puppeteer';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..');
const DIST = path.join(ROOT, 'dist');

const routes = JSON.parse(fs.readFileSync(path.join(DIST, 'routes.json'), 'utf8'));

const app = express();
app.use(express.static(DIST));
app.get('*', (_req, res) => res.sendFile(path.join(DIST, 'index.html')));
const server = http.createServer(app);

async function start() {
  await new Promise((resolve) => server.listen(0, resolve));
  const port = server.address().port;
  const baseUrl = `http://127.0.0.1:${port}`;

  const launchOpts = { headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] };
  if (process.env.PUPPETEER_EXECUTABLE_PATH) {
    launchOpts.executablePath = process.env.PUPPETEER_EXECUTABLE_PATH;
  }
  const browser = await puppeteer.launch(launchOpts);

  for (const route of routes) {
    const page = await browser.newPage();
    const url = `${baseUrl}${route}`;
    try {
      await page.goto(url, { waitUntil: 'networkidle0', timeout: 15000 });
    } catch (e) {
      console.warn(`prerender warn ${route}: ${e.message}`);
    }
    const html = await page.content();
    const outDir = path.join(DIST, route);
    fs.mkdirSync(outDir, { recursive: true });
    fs.writeFileSync(path.join(outDir, 'index.html'), html);
    console.log(`prerender: ${route}`);
    await page.close();
  }

  await browser.close();
  server.close();
}

start().catch((e) => {
  console.error(e);
  process.exit(1);
});
