import { rollupPluginAstroBuildHTML } from "../../vite-plugin-build-html/index.js";
import { rollupPluginAstroBuildCSS } from "../../vite-plugin-build-css/index.js";
import fs from "fs";
import * as colors from "kleur/colors";
import { performance } from "perf_hooks";
import vite from "../vite.js";
import { fileURLToPath } from "url";
import { createVite } from "../create-vite.js";
import { debug, defaultLogOptions, info, levels, timerMessage, warn } from "../logger.js";
import { preload as ssrPreload } from "../ssr/index.js";
import { generatePaginateFunction } from "../ssr/paginate.js";
import { createRouteManifest, validateGetStaticPathsModule, validateGetStaticPathsResult } from "../ssr/routing.js";
import { generateRssFunction } from "../ssr/rss.js";
import { generateSitemap } from "../ssr/sitemap.js";
async function build(config, options = { logging: defaultLogOptions }) {
  const builder = new AstroBuilder(config, options);
  await builder.build();
}
class AstroBuilder {
  constructor(config, options) {
    this.mode = "production";
    this.routeCache = {};
    if (!config.buildOptions.site && config.buildOptions.sitemap !== false) {
      warn(options.logging, "config", `Set "buildOptions.site" to generate correct canonical URLs and sitemap`);
    }
    if (options.mode)
      this.mode = options.mode;
    this.config = config;
    const port = config.devOptions.port;
    this.logging = options.logging;
    this.origin = config.buildOptions.site ? new URL(config.buildOptions.site).origin : `http://localhost:${port}`;
    this.manifest = createRouteManifest({ config });
  }
  async build() {
    const { logging, origin } = this;
    const timer = {};
    timer.init = performance.now();
    timer.viteStart = performance.now();
    const viteConfig = await createVite(vite.mergeConfig({
      mode: this.mode,
      server: {
        hmr: { overlay: false },
        middlewareMode: "ssr"
      }
    }, this.config.vite || {}), { astroConfig: this.config, logging });
    const viteServer = await vite.createServer(viteConfig);
    this.viteServer = viteServer;
    debug(logging, "build", timerMessage("Vite started", timer.viteStart));
    timer.loadStart = performance.now();
    const assets = {};
    const allPages = {};
    await Promise.all(this.manifest.routes.map(async (route) => {
      var _a;
      if (route.pathname) {
        allPages[route.component] = {
          route,
          paths: [route.pathname],
          preload: await ssrPreload({
            astroConfig: this.config,
            filePath: new URL(`./${route.component}`, this.config.projectRoot),
            logging,
            mode: "production",
            origin,
            pathname: route.pathname,
            route,
            routeCache: this.routeCache,
            viteServer
          }).then((routes) => {
            const html = `${route.pathname}`.replace(/\/?$/, "/index.html");
            debug(logging, "build", `\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component} \u2192 ${colors.yellow(html)}`);
            return routes;
          }).catch((err) => {
            debug(logging, "build", `\u251C\u2500\u2500 ${colors.bold(colors.red("\u2718"))} ${route.component}`);
            throw err;
          })
        };
        return;
      }
      const result = await this.getStaticPathsForRoute(route).then((routes) => {
        const label = routes.paths.length === 1 ? "page" : "pages";
        debug(logging, "build", `\u251C\u2500\u2500 ${colors.bold(colors.green("\u2714"))} ${route.component} \u2192 ${colors.magenta(`[${routes.paths.length} ${label}]`)}`);
        return routes;
      }).catch((err) => {
        debug(logging, "build", `\u251C\u2500\u2500 ${colors.bold(colors.red("\u2717"))} ${route.component}`);
        throw err;
      });
      if ((_a = result.rss) == null ? void 0 : _a.xml) {
        const rssFile = new URL(result.rss.url.replace(/^\/?/, "./"), this.config.dist);
        if (assets[fileURLToPath(rssFile)]) {
          throw new Error(`[getStaticPaths] RSS feed ${result.rss.url} already exists.
Use \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})`);
        }
        assets[fileURLToPath(rssFile)] = result.rss.xml;
      }
      allPages[route.component] = {
        route,
        paths: result.paths,
        preload: await ssrPreload({
          astroConfig: this.config,
          filePath: new URL(`./${route.component}`, this.config.projectRoot),
          logging,
          mode: "production",
          origin,
          pathname: result.paths[0],
          route,
          routeCache: this.routeCache,
          viteServer
        })
      };
    }));
    debug(logging, "build", timerMessage("All pages loaded", timer.loadStart));
    const pureCSSChunks = new Set();
    const chunkToReferenceIdMap = new Map();
    const astroStyleMap = new Map();
    const astroPageStyleMap = new Map();
    const pageNames = [];
    timer.buildStart = performance.now();
    await vite.build({
      logLevel: "error",
      mode: "production",
      build: {
        emptyOutDir: true,
        minify: "esbuild",
        outDir: fileURLToPath(this.config.dist),
        rollupOptions: {
          input: [],
          output: { format: "esm" }
        },
        target: "es2020"
      },
      plugins: [
        rollupPluginAstroBuildHTML({
          astroConfig: this.config,
          astroPageStyleMap,
          astroStyleMap,
          chunkToReferenceIdMap,
          pureCSSChunks,
          logging,
          origin,
          allPages,
          pageNames,
          routeCache: this.routeCache,
          viteServer
        }),
        rollupPluginAstroBuildCSS({
          astroPageStyleMap,
          astroStyleMap,
          chunkToReferenceIdMap,
          pureCSSChunks
        }),
        ...viteConfig.plugins || []
      ],
      publicDir: viteConfig.publicDir,
      root: viteConfig.root,
      server: viteConfig.server,
      base: this.config.buildOptions.site ? new URL(this.config.buildOptions.site).pathname : "/"
    });
    debug(logging, "build", timerMessage("Vite build finished", timer.buildStart));
    timer.assetsStart = performance.now();
    Object.keys(assets).map((k) => {
      if (!assets[k])
        return;
      const filePath = new URL(`file://${k}`);
      fs.mkdirSync(new URL("./", filePath), { recursive: true });
      fs.writeFileSync(filePath, assets[k], "utf8");
      delete assets[k];
    });
    debug(logging, "build", timerMessage("Additional assets copied", timer.assetsStart));
    timer.sitemapStart = performance.now();
    if (this.config.buildOptions.sitemap && this.config.buildOptions.site) {
      const sitemap = generateSitemap(pageNames.map((pageName) => new URL(`/${pageName}`, this.config.buildOptions.site).href));
      const sitemapPath = new URL("./sitemap.xml", this.config.dist);
      await fs.promises.mkdir(new URL("./", sitemapPath), { recursive: true });
      await fs.promises.writeFile(sitemapPath, sitemap, "utf8");
    }
    debug(logging, "build", timerMessage("Sitemap built", timer.sitemapStart));
    await viteServer.close();
    if (logging.level && levels[logging.level] <= levels["info"]) {
      await this.printStats({ logging, timeStart: timer.init, pageCount: pageNames.length });
    }
  }
  async getStaticPathsForRoute(route) {
    if (!this.viteServer)
      throw new Error(`vite.createServer() not called!`);
    const filePath = new URL(`./${route.component}`, this.config.projectRoot);
    const mod = await this.viteServer.ssrLoadModule(fileURLToPath(filePath));
    validateGetStaticPathsModule(mod);
    const rss = generateRssFunction(this.config.buildOptions.site, route);
    const staticPaths = (await mod.getStaticPaths({ paginate: generatePaginateFunction(route), rss: rss.generator })).flat();
    this.routeCache[route.component] = staticPaths;
    validateGetStaticPathsResult(staticPaths, this.logging);
    return {
      paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean),
      rss: rss.rss
    };
  }
  async printStats({ logging, timeStart, pageCount }) {
    debug(logging, "");
    const buildTime = performance.now() - timeStart;
    const total = buildTime < 750 ? `${Math.round(buildTime)}ms` : `${(buildTime / 1e3).toFixed(2)}s`;
    const perPage = `${Math.round(buildTime / pageCount)}ms`;
    info(logging, "build", `${pageCount} pages built in ${colors.bold(total)} ${colors.dim(`(${perPage}/page)`)}`);
    info(logging, "build", `\u{1F680} ${colors.cyan(colors.bold("Done"))}`);
  }
}
export {
  build as default
};
//# sourceMappingURL=data:application/json;base64, 
