/**
 * Detect system-generated user messages that aren't real human prompts.
 * These should be skipped entirely when looking for meaningful prompts.
 */
export function isSystemGeneratedMessage(text: string): boolean {
  return (
    text.startsWith("[Request interrupted by user") ||
    text.startsWith("<command-name>") ||
    text.startsWith("<command-message>") ||
    text.startsWith("<local-command-caveat>") ||
    text.startsWith("<local-command-stdout>") ||
    text.startsWith("<task-notification>") ||
    text.startsWith("<bash-input>") ||
    text.startsWith("<bash-stdout>")
  );
}

/** Cleaned prompt clipped to ~200 chars for list/preview display. */
export function previewPrompt(text: string): string {
  return cleanPromptText(text).slice(0, 200);
}

/**
 * Strip system-injected boilerplate from user prompts.
 * Shared by discover (session scanning) and server (API responses).
 */
export function cleanPromptText(text: unknown): string {
  if (typeof text !== "string") return "";

  let cleaned = text.trim();
  if (!cleaned) return "";
  if (looksLikeConversationSummary(cleaned)) return "";

  const hadTerminalNoise =
    /Last login:|gh auth status|github\.com|credential\.helper=|branch\./i.test(cleaned);

  cleaned = stripSlackPreamble(cleaned);
  cleaned = stripTerminalTranscriptNoise(cleaned);

  if (/<attached_files>|<code_selection\b/i.test(cleaned)) {
    return "";
  }

  // Strip XML-style tags (e.g. <local-command-caveat>, <command-name>, <code_selection ...>)
  cleaned = cleaned.replace(/<\/?[a-z][^>]*>/gi, "");
  cleaned = cleaned.replace(/^\s*\d+\|\s*/gm, "");
  // Remove known Claude Code local-command boilerplate
  cleaned = cleaned.replace(
    /Caveat:\s*The messages below were generated by the user while running local commands\.[^.]*/g,
    "",
  );
  cleaned = cleaned.replace(/DO NOT respond to these messages[^.]*/g, "");
  // Remove slash commands (e.g. "/clear clear", "/resume resume")
  cleaned = cleaned.replace(/^\/\w+\s*/g, "");
  // Collapse whitespace
  cleaned = cleaned.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
  if (!cleaned || looksLikeConversationSummary(cleaned)) return "";
  if (hadTerminalNoise && /^[a-z0-9._:-]{1,12}$/i.test(cleaned)) return "";
  return cleaned;
}

function looksLikeConversationSummary(text: string): boolean {
  const normalized = text.trim();
  return (
    /^\[Previous conversation summary\]:/i.test(normalized) ||
    /^Summary:\s*1\.\s*Primary Request and Intent:/i.test(normalized) ||
    // Cursor sometimes stores a truncated mid-sentence summary fragment instead
    // of the real first prompt; suppress that artifact in previews.
    /^and merge infrastructure was built for human-paced output/i.test(normalized)
  );
}

function stripSlackPreamble(text: string): string {
  const lines = text.split("\n");
  const trimmed = [...lines];
  const removedSpeaker = /^\S.*\[\d{1,2}:\d{2}\s?(?:AM|PM)\]$/i.test(trimmed[0] || "");
  if (removedSpeaker) {
    trimmed.shift();
  }
  if (removedSpeaker && /^(?:hello|hi)\b/i.test((trimmed[0] || "").trim())) {
    trimmed.shift();
  }
  return trimmed.join("\n").trim();
}

function stripTerminalTranscriptNoise(text: string): string {
  const lines = text.split("\n");
  const kept = lines.filter((line) => {
    const trimmed = line.trim();
    if (!trimmed) return true;
    if (/^Last login:/i.test(trimmed)) return false;
    if (/^(?:➜|❯)\s+/.test(trimmed)) return false;
    if (/^github(?:\.com|\.rbx\.com)?$/i.test(trimmed)) return false;
    if (/^[✓✔]/.test(trimmed)) return false;
    if (/^-\s+(?:Active account|Git operations protocol|Token|Token scopes):/i.test(trimmed))
      return false;
    if (
      /^(?:credential|init|user|filter|alias|core|remote|branch)\.[^=]+=/i.test(trimmed) ||
      /^branch\.[^.]+\./i.test(trimmed)
    )
      return false;
    return true;
  });
  return kept.join("\n").trim();
}
