/**
 * Global stylesheet pipeline.
 *
 * Convention: `app/styles/global.css` is the entry. If it is absent but other
 * `app/styles/*.css` files exist, they are aggregated into one entry. The entry
 * is bundled by Bun's CSS bundler, which resolves `@import` — including from
 * node_modules — so any npm CSS framework (Bootstrap, etc.) works by importing
 * it. A custom `process` hook can replace the bundler for Tailwind/PostCSS/Sass.
 */

import { existsSync, readdirSync, mkdirSync, writeFileSync } from "node:fs";
import { isAbsolute, join, relative } from "node:path";
import type { Mode } from "./config.ts";

const fwd = (p: string) => p.replace(/\\/g, "/");

/**
 * Resolve the CSS entry for an app.
 *  - `override` (from config.styles.entry) is resolved relative to `appRoot`.
 *  - otherwise prefer `app/styles/global.css`.
 *  - otherwise aggregate all `app/styles/*.css` into a generated entry.
 * Returns null when the app has no styles.
 */
export function findStyleEntry(appDir: string, appRoot: string, override?: string): string | null {
  if (override) {
    const p = isAbsolute(override) ? override : join(appRoot, override);
    return existsSync(p) ? p : null;
  }

  const stylesDir = join(appDir, "styles");
  const globalCss = join(stylesDir, "global.css");
  if (existsSync(globalCss)) return globalCss;

  if (existsSync(stylesDir)) {
    const cssFiles = readdirSync(stylesDir)
      .filter((f) => f.endsWith(".css"))
      .sort();
    if (cssFiles.length > 0) {
      const cacheDir = join(appDir, ".wrnexus");
      mkdirSync(cacheDir, { recursive: true });
      const entry = join(cacheDir, "styles-entry.css");
      const imports = cssFiles
        .map((f) => `@import "${fwd(relative(cacheDir, join(stylesDir, f)))}";`)
        .join("\n");
      writeFileSync(entry, imports + "\n", "utf8");
      return entry;
    }
  }

  return null;
}

/**
 * Bundle a CSS entry into a single stylesheet string using Bun's CSS bundler.
 * Resolves `@import` (local and node_modules), handles nesting, minifies in prod.
 */
export async function bundleCss(entryPath: string, mode: Mode): Promise<string> {
  const result = await Bun.build({
    entrypoints: [entryPath],
    minify: mode === "production",
  });
  if (!result.success) {
    throw new Error("CSS bundle failed:\n" + result.logs.map(String).join("\n"));
  }
  const cssOutput =
    result.outputs.find((output) => output.path?.endsWith(".css")) ?? result.outputs[0];
  if (!cssOutput) throw new Error("CSS bundle produced no output.");
  return await cssOutput.text();
}
