import {
  LIST_STYLES_LI,
  LIST_STYLES_OL,
  LIST_STYLES_UL,
  STYLE_ATTR_REGEX,
} from './constants';

type ListTag = 'ul' | 'ol' | 'li';

const replaceListOpenTagStyle = (
  match: string,
  attrs: string | undefined,
  component: ListTag,
  style: string,
): string => {
  if (STYLE_ATTR_REGEX.test(attrs ?? '')) {
    return match.replace(STYLE_ATTR_REGEX, ` style="${style};`);
  }
  return `<${component}${attrs || ''} style="${style}">`;
};

/** Add target="_blank" and rel="noopener noreferrer" to all links (open links in new tab) */
export const processLinksToOpenInNewTab = (html: string): string => {
  if (!html) return '';
  return html.replace(
    /<a(.*?)>/gi,
    '<a$1 target="_blank" rel="noopener noreferrer">',
  );
};

/**
 * Block-based editors (e.g. TipTap) wrap each list item's content in a `<p>`. Combined with
 * `list-style-position:inside`, that block forces the bullet onto its own line above the text.
 * Unwrap the first `<p>` directly inside each `<li>` so the marker and content share a line,
 * while preserving any sibling blocks (extra paragraphs, nested lists, etc.) inside the item.
 */
export const unwrapListItemParagraphs = (html: string): string => {
  if (!html) return '';
  return html.replace(
    /(<li(?:\s[^>]*)?>)\s*<p(?:\s[^>]*)?>([\s\S]*?)<\/p>/gi,
    '$1$2',
  );
};

/**
 * Canonical list styling for `RichText`: injects inline styles on `ul`/`ol`/`li` so markers render
 * despite global resets. Merges with existing `style` attributes when present.
 */
export const processListStyles = (html: string): string => {
  if (!html) return '';
  return html
    .replace(/<ul(\s[^>]*)?>/gi, (match, attrs) =>
      replaceListOpenTagStyle(match, attrs, 'ul', LIST_STYLES_UL),
    )
    .replace(/<ol(\s[^>]*)?>/gi, (match, attrs) =>
      replaceListOpenTagStyle(match, attrs, 'ol', LIST_STYLES_OL),
    )
    .replace(/<li(\s[^>]*)?>/gi, (match, attrs) =>
      replaceListOpenTagStyle(match, attrs, 'li', LIST_STYLES_LI),
    );
};
