import DOMPurify from "dompurify";

const ALLOWED_TAGS = ["p", "span", "strong", "b", "em", "i", "u", "br"];
const ALLOWED_ATTR = ["style"];

export function safeHtml(input: string | null | undefined): string {
  if (!input) return "";
  return DOMPurify.sanitize(input, {
    ALLOWED_TAGS,
    ALLOWED_ATTR,
    KEEP_CONTENT: true,
  });
}

/**
 * Strip HTML markup and return the visible plain-text content. Used by
 * dialog inputs that show titles / attendee names which are stored as
 * sanitized Tiptap rich-text HTML — without this they would render the
 * raw `<p>…</p>` markup inside the input box.
 *
 * Behavior:
 *   - `<br>` becomes a newline; block boundaries (`</p>`, `</div>`) become
 *     a newline so paragraphs don't run together.
 *   - HTML entities are decoded (via the browser parser).
 *   - Whitespace is collapsed to single spaces and trimmed.
 */
export function htmlToPlainText(input: string | null | undefined): string {
  if (!input) return "";
  // Fast path: nothing that looks like markup.
  if (!/[<&]/.test(input)) return input;
  const withBreaks = input
    .replace(/<br\s*\/?>/gi, "\n")
    .replace(/<\/(p|div|li|h[1-6])>/gi, "\n");
  let text = "";
  if (typeof DOMParser !== "undefined") {
    try {
      const doc = new DOMParser().parseFromString(
        `<div>${withBreaks}</div>`,
        "text/html",
      );
      text = doc.body.textContent ?? "";
    } catch {
      text = withBreaks.replace(/<[^>]*>/g, "");
    }
  } else {
    text = withBreaks.replace(/<[^>]*>/g, "");
  }
  return text.replace(/\s+/g, " ").trim();
}

/**
 * Wrap user-supplied plain text back into the single-paragraph format
 * the inline Tiptap editor produces, so values saved from the dialog
 * stay byte-compatible with values saved from the inline cells.
 * Returns "" for empty input so callers can decide whether to send null.
 */
export function wrapAsParagraph(input: string | null | undefined): string {
  if (input == null) return "";
  const trimmed = input.trim();
  if (!trimmed) return "";
  const escaped = trimmed
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
  return `<p>${escaped}</p>`;
}
