/**
 * Helpers of the theme widgets' server-rendered previews (widgets/_theme/ServerPreview.vue).
 *
 * The canvas asks `POST /render` for the widget's real frontend HTML (render.php with the post / menu / query
 * data of WordPress) and shows it WITHOUT an extra wrapper: the root element of the server HTML is replaced by
 * the canvas root (which carries the editor attrs), its own attributes (modifier classes, aria, data-*) are merged
 * in and its inner HTML is injected. So the canvas DOM is the live DOM and the generated `.zx-<id>` CSS applies once.
 */
export interface ParsedServerHtml {
  /** Root tag name (lower case), `div` when the HTML has no element. */
  tag: string;
  /** Attributes of the server root except the ones the canvas owns (data-zx-id, data-zx-type, id, style). */
  attrs: Record<string, string>;
  /** Classes of the server root. */
  classes: string[];
  inner: string;
  /** False when the server printed nothing (e.g. a featured image on a post without one). */
  empty: boolean;
}

const OWNED = new Set(['class', 'data-zx-id', 'data-zx-type', 'id', 'style']);
const SAFE_TAG = /^[a-z][a-z0-9-]*$/;

export function parseServerHtml(html: string, doc: Document = document): ParsedServerHtml {
  const tpl = doc.createElement('template');
  tpl.innerHTML = html.trim();
  const root = tpl.content.firstElementChild;
  if (!root) return { tag: 'div', attrs: {}, classes: [], inner: '', empty: true };
  const attrs: Record<string, string> = {};
  for (const a of Array.from(root.attributes)) {
    if (OWNED.has(a.name) || /^on/i.test(a.name)) continue;
    attrs[a.name] = a.value;
  }
  const tag = root.tagName.toLowerCase();
  return {
    tag: SAFE_TAG.test(tag) && tag !== 'script' ? tag : 'div',
    attrs,
    classes: (root.getAttribute('class') ?? '').split(/\s+/).filter(Boolean),
    inner: root.innerHTML,
    empty: false,
  };
}

/** Canvas attrs + server root attrs: classes are merged (canvas first, no duplicates), canvas attributes win. */
export function mergeRootAttrs(canvas: Record<string, unknown>, parsed: ParsedServerHtml): Record<string, unknown> {
  const own = String(canvas.class ?? '')
    .split(/\s+/)
    .filter(Boolean);
  const classes = [...own];
  for (const c of parsed.classes) if (!classes.includes(c)) classes.push(c);
  return { ...parsed.attrs, ...canvas, class: classes.join(' ') };
}

/** Delay before a settings change re-renders the preview (the first render is immediate). */
export const SERVER_PREVIEW_DEBOUNCE_MS = 300;
