/** Detect empty TipTap / legacy plain description values. */
export function isSceneDescriptionEmpty(html: string | null | undefined): boolean {
  if (html == null) return true;
  const trimmed = html.trim();
  if (trimmed === '') return true;
  const text = trimmed
    .replace(/<br\s*\/?>/gi, ' ')
    .replace(/<\/(p|div|h[1-6]|li|blockquote)>/gi, ' ')
    .replace(/<[^>]+>/g, '')
    .replace(/&nbsp;/gi, ' ')
    .replace(/&#160;/g, ' ')
    .replace(/\s+/g, ' ')
    .trim();
  return text.length === 0;
}

/** Persist empty editor as '' instead of empty paragraph markup. */
export function normalizeSceneDescriptionHtml(html: string): string {
  return isSceneDescriptionEmpty(html) ? '' : html.trim();
}

const ALLOWED_TAGS = new Set([
  'P',
  'BR',
  'STRONG',
  'B',
  'EM',
  'I',
  'U',
  'S',
  'H2',
  'H3',
  'UL',
  'OL',
  'LI',
  'BLOCKQUOTE',
  'A',
  'CODE',
  'SPAN',
]);

/** Sanitize TipTap HTML for safe preview rendering. */
export function sanitizeSceneDescriptionHtml(html: string): string {
  if (typeof document === 'undefined') return html;
  if (isSceneDescriptionEmpty(html)) return '';
  if (!/<[a-z][\s\S]*>/i.test(html)) {
    const esc = document.createElement('div');
    esc.textContent = html;
    return esc.innerHTML;
  }

  const template = document.createElement('template');
  template.innerHTML = html.trim();
  const container = document.createElement('div');
  container.appendChild(template.content.cloneNode(true));

  const walk = (node: Node) => {
    if (node.nodeType === Node.ELEMENT_NODE) {
      const el = node as HTMLElement;
      const tag = el.tagName;
      if (!ALLOWED_TAGS.has(tag)) {
        const parent = el.parentNode;
        if (parent) {
          while (el.firstChild) parent.insertBefore(el.firstChild, el);
          parent.removeChild(el);
        }
        return;
      }
      for (const attr of [...el.attributes]) {
        const name = attr.name.toLowerCase();
        if (tag === 'A' && (name === 'href' || name === 'target' || name === 'rel')) {
          if (name === 'href') {
            const href = attr.value.trim();
            if (!/^(https?:|mailto:)/i.test(href)) {
              el.removeAttribute(attr.name);
            }
          }
          continue;
        }
        el.removeAttribute(attr.name);
      }
      if (tag === 'A') {
        el.setAttribute('rel', 'noopener noreferrer');
        el.setAttribute('target', '_blank');
      }
    }
    for (const child of [...node.childNodes]) walk(child);
  };

  // Walk children only — never treat the container as a removable tag
  // (that would unwrap it and leave container.innerHTML empty).
  for (const child of [...container.childNodes]) walk(child);
  return container.innerHTML;
}
