/**
 * @wrnexus/styles — global stylesheet pipeline + app config.
 *
 * Works for SSR and CSR: the bundled stylesheet is `<link>`ed into every page's
 * `<head>`, so it styles server-rendered markup and hydrated client islands
 * alike. Use any CSS framework via `@import` in global.css (npm) or via a CDN
 * link in `wrnexus.config.ts`'s `head` field.
 */

export type {
  AppConfig,
  MobileConfig,
  PwaConfig,
  StylesConfig,
  StyleProcessContext,
  Mode,
} from "./config.ts";
export { loadAppConfig, loadRawConfig, headToString, resolveProfile, loadEnv } from "./config.ts";
export { findStyleEntry, bundleCss } from "./styles.ts";
export type { FontConfig, GoogleFont, LocalFontFace, FontDisplay } from "./fonts.ts";
export { renderFontHead, renderProductionFontHead, fontCspSources } from "./fonts.ts";
export type { ThemeConfig, ThemeTokens, ResolvedTheme } from "./theme.ts";
export {
  DEFAULT_THEMES,
  THEME_COOKIE,
  THEME_CSS_HREF,
  THEME_JS_HREF,
  resolveThemeConfig,
  resolveThemeName,
  renderThemeCss,
  renderThemeRuntime,
} from "./theme.ts";

import type { Mode, StyleProcessContext, StylesConfig } from "./config.ts";
import { bundleCss } from "./styles.ts";

/**
 * Produce the final CSS for an entry: run the config's custom processor if one
 * is provided (Tailwind/PostCSS/Sass), otherwise use the built-in Bun bundler.
 *
 * If a custom processor throws (e.g. Tailwind can't resolve `tailwindcss`
 * because deps aren't installed), we DON'T crash every request — we log a clear,
 * actionable message and fall back to best-effort CSS so the app keeps serving.
 */
export async function renderStyles(
  ctx: StyleProcessContext,
  styles?: StylesConfig,
): Promise<string> {
  if (!ctx.entryPath) return "";
  if (styles?.process) {
    try {
      return String(await styles.process(ctx));
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      console.error(
        `\n[wrnexus] Stylesheet processing failed — serving un-processed CSS.\n` +
          `  ${msg.split("\n")[0]}\n` +
          `  If you use Tailwind, run \`bun install\` inside the app so \`tailwindcss\`\n` +
          `  is available (an app created inside another project may not have it).\n`,
      );
      return await fallbackCss(ctx);
    }
  }
  return bundleCss(ctx.entryPath, ctx.mode);
}

/**
 * Best-effort CSS when a custom processor fails: try the built-in bundler; if that
 * also fails (e.g. `@import "tailwindcss"` can't resolve), serve the raw entry with
 * the tool-only directives stripped so the page still renders.
 */
async function fallbackCss(ctx: StyleProcessContext): Promise<string> {
  try {
    return await bundleCss(ctx.entryPath!, ctx.mode);
  } catch {
    try {
      const raw = await Bun.file(ctx.entryPath!).text();
      return raw.replace(/@import\s+["']tailwindcss["'];?/g, "").replace(/@source[^;\n]*;?/g, "");
    } catch {
      return "";
    }
  }
}

export type { Mode as StylesMode };
