/**
 * Triage-note sanitization (Phase 21, NOTE-01).
 *
 * SECURITY-CRITICAL. This module exists so that no raw secret, token, or full
 * malicious URL query string ever reaches an Autotask note posted by Pulse.
 * `formatTriageNote()` (triage-note-format.ts) routes every URL and its final
 * assembled output through these two pure functions before returning text
 * that gets written to `TicketNotes`.
 *
 * Two things this module deliberately does NOT redact, per
 * `.planning/phases/21-autotask-triage-note/21-CONTEXT.md` (Claude's
 * Discretion): bare sender email addresses and attachment hashes. Those are
 * evidence about the phishing campaign itself, not credentials belonging to
 * Pulse or its operators — an analyst needs to see them to triage.
 */

export const REDACTED_MARKER = '[REDACTED]';

/** Keys that indicate a credential-bearing query param. Broad on purpose —
 * false positives (redacting a benign param) are acceptable; leaking a real
 * token is not. */
const CREDENTIAL_QUERY_KEY_PATTERN = /token|secret|password|api[_-]?key|key|credential/i;

/** Matches a `key=value` pair inside a query string / free text where `key`
 * looks like a credential. Value is greedy up to the next `&`, whitespace, or
 * end of string. */
const CREDENTIAL_PARAM_REGEX = /\b([A-Za-z_][A-Za-z0-9_-]*)=([^&\s]+)/g;

/** Matches `Bearer <token>` or `Authorization: <value>` sequences. */
const BEARER_AUTH_REGEX = /\b(Bearer\s+|Authorization:\s*)([^\s,;]+)/gi;

/** Matches a full http(s) URL substring embedded in free text. */
const URL_IN_TEXT_REGEX = /\bhttps?:\/\/[^\s)]+/gi;

/**
 * Strip a URL down to scheme+host+path — query string and fragment are ALWAYS
 * removed, never selectively kept, even for seemingly-benign params. This
 * satisfies NOTE-01's "no full malicious URL query strings" requirement
 * without needing to distinguish safe from unsafe params.
 *
 * Never throws: a malformed/non-URL string falls back to truncating at the
 * first `?` or `#`, returning the head unchanged if neither is present.
 */
export function sanitizeUrl(value: string): string {
  if (!value) return value;

  try {
    const url = new URL(value);
    return url.origin + url.pathname;
  } catch {
    const cutIndex = value.search(/[?#]/);
    return cutIndex === -1 ? value : value.slice(0, cutIndex);
  }
}

/**
 * Redact secrets/tokens from free text destined for an Autotask note, and
 * strip query strings from any embedded URLs. Order matters: Bearer/
 * Authorization sequences first (they don't look like `key=value` pairs so
 * they wouldn't otherwise be caught), then credential query-param
 * assignments, then any remaining full URL substrings via `sanitizeUrl`.
 *
 * Bare email addresses and hex attachment hashes are intentionally left
 * untouched — see module doc-comment.
 */
export function sanitizeNoteText(text: string): string {
  if (!text) return text;

  let out = text.replace(BEARER_AUTH_REGEX, REDACTED_MARKER);

  out = out.replace(CREDENTIAL_PARAM_REGEX, (match, key: string, val: string) => {
    if (CREDENTIAL_QUERY_KEY_PATTERN.test(key)) {
      return `${key}=${REDACTED_MARKER}`;
    }
    return match;
  });

  out = out.replace(URL_IN_TEXT_REGEX, (match) => sanitizeUrl(match));

  return out;
}
