/**
 * Branded terminal banner for the madarX OS CLI.
 *
 * Renders a block-letter MADARX wordmark plus a boxed info panel, in the
 * product palette (mars red #c2452a, gold #d4b77f, sand #f6f3ed, muted #68707b),
 * using 24-bit truecolor ANSI. Dependency-free — node builtins only — so it is
 * safe to import from the CLI supervisor (lib/cli/run.js) without pulling in the
 * runtime or opening the database.
 *
 * Honors NO_COLOR / non-TTY (plain output) and FORCE_COLOR (colorize anyway).
 */

// ── palette ────────────────────────────────────────────────────────────────
const PALETTE = {
  mars:   [0xc2, 0x45, 0x2a], // brand primary / THE accent
  marsHi: [0xde, 0x6a, 0x53], // lighter mars (top of gradient)
  marsLo: [0x7c, 0x2b, 0x19], // dark mars (bottom of gradient)
  gold:   [0xd4, 0xb7, 0x7f],
  sand:   [0xf6, 0xf3, 0xed],
  ink:    [0x68, 0x70, 0x7b], // "muted" — used for secondary text
  green:  [0x4c, 0xae, 0x6a],
  // ── Sovereign-Mono palette (brand-guidelines v1.3) — used by the splash ──
  onyx:     [0x0F, 0x0F, 0x11], // ground / black letter fill
  platinum: [0xE8, 0xE8, 0xE5], // mark / wordmark / "done" ✓
  bone:     [0xDC, 0xDC, 0xD8], // body labels
  graphite: [0x4A, 0x4A, 0x4D], // rules, borders, pending ·
  muted:    [0x8A, 0x82, 0x78], // datelines, subtitle, secondary
};

export function colorEnabled() {
  if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0') return true;
  if (process.env.NO_COLOR) return false;
  return Boolean(process.stdout && process.stdout.isTTY);
}

const ON = colorEnabled();

export function fg([r, g, b], s) {
  if (!ON) return s;
  return `\x1b[38;2;${r};${g};${b}m${s}\x1b[0m`;
}
export function bold(s) { return ON ? `\x1b[1m${s}\x1b[0m` : s; }
export function dim(s) { return ON ? `\x1b[2m${s}\x1b[0m` : s; }

/** Visible (printable) length of a string, ignoring ANSI escape sequences. */
export function visibleLength(s) {
  // eslint-disable-next-line no-control-regex
  return String(s).replace(/\x1b\[[0-9;]*m/g, '').length;
}

// ── wordmark ─────────────────────────────────────────────────────────────────
// Embedded figlet "Standard" font art for "madar" + "X", captured offline so the
// banner stays dependency-free (no figlet at runtime). "madar" renders in Sand,
// the "X" in Mars — the single brand accent (the X is a permanent constant, so
// it never counts against the one-Mars-per-surface rule).
const FIG_MADAR = [
  '                      _            ',
  '  _ __ ___   __ _  __| | __ _ _ __ ',
  " | '_ ` _ \\ / _` |/ _` |/ _` | '__|",
  ' | | | | | | (_| | (_| | (_| | |   ',
  ' |_| |_| |_|\\__,_|\\__,_|\\__,_|_|   ',
  '                                   ',
];
const FIG_X = [
  ' __  __',
  ' \\ \\/ /',
  '  \\  / ',
  '  /  \\ ',
  ' /_/\\_\\',
  '       ',
];

/** The "madarX" wordmark as a colored, multi-line string. */
export function wordmark() {
  const rows = Math.max(FIG_MADAR.length, FIG_X.length);
  const lines = [];
  for (let i = 0; i < rows; i++) {
    const l = FIG_MADAR[i] ?? '';
    const r = FIG_X[i] ?? '';
    lines.push(fg(PALETTE.platinum, l) + fg(PALETTE.mars, r));
  }
  return lines.join('\n');
}

// ── panel ────────────────────────────────────────────────────────────────────
const PANEL_WIDTH = 64;

function rule(char = '─') { return fg(PALETTE.gold, char.repeat(PANEL_WIDTH)); }

/** A "label: value" line with a mars label and sand value. */
function field(label, value) {
  const lab = fg(PALETTE.mars, `${label}`);
  return `  ${lab}${dim(' · ')}${fg(PALETTE.sand, String(value))}`;
}

/**
 * Render the full banner.
 *
 * @param {object} info
 * @param {string} info.version    installed version (e.g. "2.9.5")
 * @param {string} [info.tagline]  one-line product tagline
 * @param {string} [info.home]     data home path
 * @param {string} [info.url]      dashboard URL
 * @param {string} [info.engine]   default sub-agent engine
 * @param {string} [info.latest]   latest published version (for the update hint)
 * @param {boolean}[info.behind]   true if a newer version exists
 * @param {string} [info.subtitle] small right-aligned subtitle by the wordmark
 * @param {number} [info.tools]    tool-catalog count
 * @param {number} [info.skills]   skill-catalog count
 * @returns {string}
 */
export function renderBanner(info = {}) {
  const {
    version = '0.0.0',
    tagline = 'local-first agent orchestrator',
    home,
    url,
    engine,
    latest,
    behind = false,
    subtitle,
    tools,
    skills,
  } = info;

  const out = [];
  out.push('');
  out.push(wordmark());
  out.push('');
  // Title line: brand wordmark + version, gold rule under it.
  const title = `${bold(fg(PALETTE.sand, 'madar'))}${bold(fg(PALETTE.mars, 'X'))}${bold(fg(PALETTE.sand, ' OS'))}`;
  const ver = fg(PALETTE.gold, `v${version}`);
  const sub = subtitle ? dim(`  ${subtitle}`) : '';
  out.push(`  ${title} ${ver}${sub}`);
  out.push(`  ${dim(tagline)}`);
  out.push(rule());

  if (home) out.push(field('data home', home));
  if (url) out.push(field('dashboard', url));
  if (engine) out.push(field('engine   ', engine));

  if (Number.isFinite(tools) || Number.isFinite(skills)) {
    const parts = [];
    if (Number.isFinite(tools)) parts.push(`${fg(PALETTE.gold, tools)} ${fg(PALETTE.sand, 'tools')}`);
    if (Number.isFinite(skills)) parts.push(`${fg(PALETTE.gold, skills)} ${fg(PALETTE.sand, 'skills')}`);
    out.push(`  ${fg(PALETTE.mars, 'catalog  ')}${dim(' · ')}${parts.join(dim(' · '))}`);
  }

  out.push(rule());

  if (behind && latest) {
    out.push(`  ${fg(PALETTE.gold, '⚠')}  ${fg(PALETTE.sand, `v${latest} available`)} ${dim('— run')} ${fg(PALETTE.mars, 'madarx update')}`);
  } else {
    out.push(`  ${fg(PALETTE.green, '●')}  ${dim('up to date')}`);
  }
  out.push('');
  return out.join('\n');
}

/** Compact one-block wordmark + title only (for the setup wizard header). */
export function renderHeader(title = 'setup', version) {
  const out = ['', wordmark(), ''];
  const t = `${bold(fg(PALETTE.sand, 'madar'))}${bold(fg(PALETTE.mars, 'X'))}${bold(fg(PALETTE.sand, ' OS'))}`;
  const ver = version ? fg(PALETTE.gold, ` v${version}`) : '';
  out.push(`  ${t}${ver} ${dim('—')} ${fg(PALETTE.mars, title)}`);
  out.push(rule());
  out.push('');
  return out.join('\n');
}

// ── hero banner (Hermes-style: 3D wordmark + orbit mark + grouped catalog) ────

/**
 * Hero wordmark — identical to the install splash: the lowercase Standard
 * "madar" (FIG_MADAR, Platinum) beside the Standard "X" (FIG_X, Mars).
 * Returns an array of lines so the hero can indent/compose them.
 */
function heroWordmark() {
  return wordmark().split('\n');
}

// Orbit mark — "madar" (مدار) is Arabic for orbit. Graphite ring, Mars core + bead.
const ORBIT = [
  '   ╭───────╮ ● ',
  ' ╭─╯       ╰─╮ ',
  '│     ╲ ╱     │',
  '│      ╳      │',
  '│     ╱ ╲     │',
  ' ╰─╮       ╭─╯ ',
  '   ╰───────╯   ',
];
function orbitMark() {
  return ORBIT.map((line) => {
    let out = '';
    for (const ch of line) {
      if (ch === ' ') out += ' ';
      else if (ch === '╳' || ch === '╲' || ch === '╱' || ch === '●') out += fg(PALETTE.mars, ch);
      else out += fg(PALETTE.graphite, ch);
    }
    return out;
  });
}

/** Truncate raw (uncolored) text to a visible width with an ellipsis. */
function clip(s, width) {
  if (s.length <= width) return s;
  return s.slice(0, Math.max(0, width - 1)) + '…';
}

/**
 * Hermes-style hero banner: a big 3D MADARX wordmark, a titled rule, then a
 * two-column body — orbit mark + runtime meta on the left, a grouped capability
 * catalog (tools by category, then skills) on the right.
 *
 * Dependency-free and DB-free: all inputs are passed in by the caller (the CLI
 * supervisor), so importing this never opens the database.
 *
 * @param {object} info
 * @param {string}  info.version
 * @param {string} [info.home]      data home path
 * @param {string} [info.url]       dashboard URL
 * @param {string} [info.engine]    default sub-agent engine
 * @param {string} [info.commit]    short git hash (optional)
 * @param {string} [info.session]   session id (optional)
 * @param {Array<{category:string,count:number,names:string[]}>} [info.toolCats]
 * @param {number} [info.toolCount]
 * @param {Array<{category:string,count:number,names:string[]}>} [info.skillGroups]
 * @param {number} [info.skillCount]
 * @param {boolean}[info.behind]
 * @param {string} [info.latest]
 * @returns {string}
 */
export function renderHeroBanner(info = {}) {
  const {
    version = '0.0.0', home, url,
    commit, session, toolCats = [], toolCount, skillGroups = [], skillCount,
    behind = false, latest,
  } = info;

  const cols = (process.stdout && process.stdout.columns) || 84;
  const out = [''];

  // 1) 3D wordmark.
  for (const l of heroWordmark()) out.push('  ' + l);
  out.push('');

  // 2) Titled rule: ── madarX OS v… · date · commit ─────────
  const stamp = new Date().toISOString().slice(0, 10).replace(/-/g, '.');
  const title = `${bold(fg(PALETTE.platinum, 'madar'))}${bold(fg(PALETTE.mars, 'X'))}${bold(fg(PALETTE.platinum, ' OS'))}`
    + ` ${fg(PALETTE.mars, 'v' + version)}`
    + fg(PALETTE.muted, `  ·  ${stamp}${commit ? '  ·  ' + commit : ''}`);
  const titleVis = visibleLength(title);
  const railLen = Math.max(3, cols - 4 - titleVis - 3);
  out.push('  ' + fg(PALETTE.graphite, '── ') + title + ' ' + fg(PALETTE.graphite, '─'.repeat(railLen)));
  out.push('');

  // 3) Two columns. Left: orbit mark + meta. Right: catalog.
  const left = orbitMark();
  const leftMeta = [
    '',
    home ? '  ' + fg(PALETTE.muted, home.replace(process.env.HOME || '~', '~')) : '',
    url ? '  ' + fg(PALETTE.muted, url) : '',
    session ? '  ' + fg(PALETTE.muted, 'session ' + session) : '',
  ].filter(Boolean);
  const leftAll = [...left, ...leftMeta];
  // Left column width = its widest line (orbit block or the longer meta lines
  // like the dashboard URL / session id), so the right column never collides
  // with the address/session under the logo.
  const LW = Math.max(...leftAll.map(visibleLength));
  const GAP = 6; // breathing room between the two columns

  const right = [];
  const rw = Math.max(28, cols - LW - GAP - 2);
  // One "label: a, b, c…" row, clipped to the right column.
  const groupLine = (label, names) => {
    const body = clip(names.join(', '), rw - label.length - 2);
    return `${fg(PALETTE.bone, label + ':')} ${fg(PALETTE.muted, body)}`;
  };

  right.push(fg(PALETTE.mars, bold('Available Tools')) + fg(PALETTE.muted, toolCount ? `  ${toolCount}` : ''));
  // Feature the toolsets a business agent actually reaches for, in priority
  // order — not raw count. Domain/installable packs (mines, travel,
  // cli_generator, vercel, …) stay in the registry but fold into "more toolsets".
  const FEATURED_TOOL_CATEGORIES = [
    'web', 'email', 'calendar', 'local_machine', 'browser',
    'supabase', 'workflow', 'authoring', 'github', 'voice',
  ];
  // Friendly display labels for the slugs that read like internals.
  const TOOL_LABELS = {
    local_machine: 'files', web: 'web', email: 'email', calendar: 'calendar',
    browser: 'browser', supabase: 'data', workflow: 'automations',
    authoring: 'build-tools', github: 'github', voice: 'voice',
  };
  const byName = new Map(toolCats.map((c) => [c.category, c]));
  const featured = FEATURED_TOOL_CATEGORIES.map((n) => byName.get(n)).filter(Boolean);
  const shownCats = featured.slice(0, 8);
  for (const c of shownCats) right.push(groupLine(TOOL_LABELS[c.category] || c.category, c.names));
  const moreCats = toolCats.length - shownCats.length;
  if (moreCats > 0) right.push(fg(PALETTE.muted, `(and ${moreCats} more toolsets…)`));

  right.push('');
  right.push(fg(PALETTE.mars, bold('Available Skills')) + fg(PALETTE.muted, skillCount ? `  ${skillCount}` : ''));
  // Business-default skills, grouped by category (research, comms, …).
  for (const g of skillGroups) right.push(groupLine(g.category, g.names));

  // Zip columns.
  const rows = Math.max(leftAll.length, right.length);
  for (let i = 0; i < rows; i++) {
    const l = leftAll[i] ?? '';
    const r = right[i] ?? '';
    const pad = ' '.repeat(Math.max(0, LW - visibleLength(l)));
    out.push('  ' + (l || '') + pad + ' '.repeat(GAP) + r);
  }

  // 4) Update status footer + dateline.
  out.push('');
  if (behind && latest) {
    out.push('  ' + fg(PALETTE.mars, '▲') + '  ' + fg(PALETTE.bone, `v${latest} available`) + fg(PALETTE.muted, '  — run ') + fg(PALETTE.mars, 'madarx update'));
  } else {
    out.push('  ' + fg(PALETTE.muted, '●  up to date'));
  }
  out.push('  ' + fg(PALETTE.muted, `${stamp}  ·  Designed in UAE  ·  v${version}`));
  out.push('');
  return out.join('\n');
}

export const _palette = PALETTE;
