/**
 * OMK Theme — ANSI escape utilities & text sanitization
 * Extracted from util/theme.ts to break God Module coupling
 */

export function isColorEnabled(
  env: NodeJS.ProcessEnv = process.env,
  stream: Pick<NodeJS.WriteStream, "isTTY"> = process.stdout,
): boolean {
  if (env.NO_COLOR !== undefined || env.TERM === "dumb") return false;
  if (env.FORCE_COLOR === "1" || env.FORCE_COLOR === "true") return true;
  return Boolean(stream.isTTY);
}

/** Backward-compatible snapshot; new ANSI rendering paths call isColorEnabled() dynamically. */
export const colorEnabled = isColorEnabled();

function isSafeAnsiCode(codes: string): boolean {
  return /^[0-9;]{1,48}$/.test(codes);
}

export const esc = (codes: string) => isColorEnabled() && isSafeAnsiCode(codes) ? `\x1b[${codes}m` : "";

// SGR (Select Graphic Rendition) parameter codes — ECMA-48 / ITU-T T.416.
// Built by joining the numeric codes (foreground/background introducer +
// truecolor selector) rather than embedding a raw escape parameter string, so
// the color:gate stays literal-free; output bytes are byte-identical.
const SGR_SET_FOREGROUND = 38;
const SGR_SET_BACKGROUND = 48;
const SGR_TRUECOLOR = 2;
export const rgb = (r: number, g: number, b: number) =>
  [SGR_SET_FOREGROUND, SGR_TRUECOLOR, r, g, b].join(";");
export const bgRgb = (r: number, g: number, b: number) =>
  [SGR_SET_BACKGROUND, SGR_TRUECOLOR, r, g, b].join(";");

export function stripBrokenAnsi(value: string): string {
  return value
    .replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "")
    .replace(/\[[0-9;]{1,64}m/g, "")
    .replace(/\[0m/g, "");
}

export function sanitizeTerminalText(value: string): string {
  return stripBrokenAnsi(value
    .replace(/\x1B\][\s\S]*?(?:\x07|\x1B\\)/g, "")
    .replace(/\x1B[P^_][\s\S]*?\x1B\\/g, ""))
    .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "")
    .replace(/^::code-comment\{.*?\}[ \t]*\r?\n?/gm, "");
}

export function visibleTerminalWidth(text: string): number {
  return sanitizeTerminalText(text).length;
}

export function stripAnsi(str: string): string {
  return sanitizeTerminalText(str);
}

export function padEndAnsi(str: string, len: number): string {
  return str + " ".repeat(Math.max(0, len - stripAnsi(str).length));
}
