/**
 * The child process launched by the dev supervisor.
 *
 *   bun run serve-entry.ts <appDir> <port> <mode> [hostname]
 *
 * It starts the dev server and prints the route table. Because it runs in its
 * own process, every restart re-imports all route modules fresh — that is how
 * the supervisor delivers live reload of edited server code.
 */

import { readFileSync } from "node:fs";
import { dirname } from "node:path";
import type { Mode } from "@wrnexus/core";
import { findStyleEntry, headToString, loadAppConfig, renderFontHead } from "@wrnexus/styles";
import { startServer } from "./index.ts";

const [appDir, portStr, modeStr, hostname, hmrStr, certFile, keyFile] = process.argv.slice(2);

const mode = (modeStr as Mode) || "development";

const port = Number(portStr) || 3000;

if (!appDir) {
  throw new Error("WRN-DEV-APP-DIR: app directory argument is required.");
}

// Load optional wrnexus.config.ts next to the app directory.
const appRoot = dirname(appDir);

const config = await loadAppConfig(appRoot);

const styleEntry = findStyleEntry(appDir, appRoot, config.styles?.entry);

const server = await startServer({
  appDir: appDir!,
  appConfig: {
    ...config,
  },

  port,
  hostname,
  tls:
    certFile && keyFile
      ? { cert: readFileSync(certFile, "utf8"), key: readFileSync(keyFile, "utf8") }
      : undefined,
  mode,
  hmr: hmrStr === undefined ? undefined : hmrStr === "true",

  styleEntry,
  stylesConfig: config.styles,

  head: [renderFontHead(config.fonts), headToString(config.head)].filter(Boolean).join("\n    "),

  seo: config.seo,
  security: config.security,
  theme: config.theme,
  i18n: config.i18n,
  db: config.db,
  databases: config.databases,
  realtime: config.realtime,
  storage: config.storage,
  mobile: config.mobile,
  pwa: config.pwa,
  devToolbar: config.devToolbar,
  plugins: config.plugins,
  observability: config.observability,
  tenancy: config.tenancy,
  navigation: config.navigation,
});

const router = server.router;

interface PrintableRoute {
  raw: string;
}

function printRouteGroup(label: string, items: readonly PrintableRoute[]): void {
  const routes = Array.from(new Set(items.map((item) => item.raw.trim()).filter(Boolean))).sort(
    (left, right) => left.localeCompare(right),
  );

  console.log(`  ${label}: ${routes.length}`);

  if (routes.length === 0) {
    console.warn(`    ⚠ No ${label.toLowerCase()} registered`);
    return;
  }

  for (const route of routes) {
    console.log(`    ${route}`);
  }
}

console.log(`\n  ⚡ WrNexus — ${server.url}\n`);

printRouteGroup("Pages", router.pages);

console.log("");

printRouteGroup("API Routes", router.api);

if (router.realtime.length > 0) {
  console.log("");

  printRouteGroup("Realtime Routes", router.realtime);
}

console.log(`\n  Components: ${router.components.length}`);

console.log("");
