/**
 * Detect a stale Vite UI bundle: server restarts pick up TS changes, but
 * express.static still serves web/dist until `npm run build:web` runs.
 */
import fs from 'node:fs';
import path from 'node:path';

export const STALE_BUNDLE_MSG =
  '⚠ web UI is STALE — built before the last source change. Run: npm run build:web, then hard-refresh.';

/** Newest file mtime (ms) under `dir`, or null if missing / empty. */
export function newestMtime(dir: string): number | null {
  if (!fs.existsSync(dir)) return null;
  let newest: number | null = null;
  const walk = (d: string) => {
    let entries: fs.Dirent[];
    try {
      entries = fs.readdirSync(d, { withFileTypes: true });
    } catch {
      return;
    }
    for (const ent of entries) {
      const p = path.join(d, ent.name);
      if (ent.isDirectory()) {
        walk(p);
        continue;
      }
      if (!ent.isFile()) continue;
      try {
        const t = fs.statSync(p).mtimeMs;
        if (newest == null || t > newest) newest = t;
      } catch {
        /* ignore */
      }
    }
  };
  walk(dir);
  return newest;
}

export interface WebBundleFreshness {
  stale: boolean;
  srcMtime: number | null;
  distMtime: number | null;
}

/** True when web/dist is missing or older than the newest file under web/src. */
export function webBundleFreshness(root: string): WebBundleFreshness {
  const srcMtime = newestMtime(path.join(root, 'web', 'src'));
  const distMtime = newestMtime(path.join(root, 'web', 'dist'));
  if (srcMtime == null) return { stale: false, srcMtime, distMtime };
  if (distMtime == null) return { stale: true, srcMtime, distMtime };
  return { stale: distMtime < srcMtime, srcMtime, distMtime };
}

/** Inject a fixed top banner into index.html (idempotent). Visible in the UI. */
export function injectStaleBanner(html: string): string {
  if (html.includes('id="rha-stale-bundle-banner"')) return html;
  const banner = [
    '<div id="rha-stale-bundle-banner" role="alert" style="',
    'position:fixed;top:0;left:0;right:0;z-index:9999;',
    'background:#d9a441;color:#000;padding:6px 12px;',
    'font:13px monospace;text-align:center">',
    STALE_BUNDLE_MSG,
    '</div>',
    '<style>body{padding-top:36px !important}</style>',
  ].join('');
  if (/<body[^>]*>/i.test(html)) {
    return html.replace(/<body[^>]*>/i, m => `${m}\n${banner}\n`);
  }
  return banner + html;
}
