function emitJsxSource(nodes, options) {
  const indent = options.indent ?? 0;
  return nodes.map((n) => emitNode(n, indent, options.imports)).join("\n");
}
const ATTR_BREAK_WIDTH = 80;
function emitNode(node, indent, imports) {
  const pad = " ".repeat(indent);
  if (node.component === "__text__") {
    return `${pad}${node.props?.text ?? ""}`;
  }
  if (node.component === "__todo__") {
    const msg = node.props?.message ?? "TODO";
    return `${pad}{/* TODO: ${msg} */}`;
  }
  if (node.component === "__when_empty__") {
    const source = node.props?.source ?? "items";
    const inner = (node.children ?? []).map((c) => emitNode(c, indent + 2, imports)).join("\n");
    return [
      `${pad}{${source}.length === 0 && (`,
      inner,
      `${pad})}`
    ].join("\n");
  }
  if (node.component === "__when__") {
    const condition = node.props?.condition ?? "true";
    const inner = (node.children ?? []).map((c) => emitNode(c, indent + 2, imports)).join("\n");
    return [
      `${pad}{${condition} && (`,
      inner,
      `${pad})}`
    ].join("\n");
  }
  const isComposite = /^[A-Z]/.test(node.component);
  if (isComposite) imports.add(node.component);
  const attrParts = formatAttrParts(node.props, node.expressions);
  const inlineAttrs = attrParts.length > 0 ? " " + attrParts.join(" ") : "";
  const hasInlineExpression = Boolean(
    node.expressions?.children && (!node.children || node.children.length === 0)
  );
  const hasSingleTextChild = Boolean(
    node.children?.length === 1 && node.children[0].component === "__text__" && !node.children[0].iterate
  );
  const isCompact = hasInlineExpression || hasSingleTextChild;
  const shouldBreakAttrs = !isCompact && inlineAttrs.length > ATTR_BREAK_WIDTH;
  const multiLineAttrs = attrParts.length > 0 ? "\n" + attrParts.map((a) => " ".repeat(indent + 2) + a).join("\n") + "\n" + pad : "";
  const attrs = shouldBreakAttrs ? multiLineAttrs : inlineAttrs;
  if (hasInlineExpression) {
    return `${pad}<${node.component}${attrs}>{${node.expressions.children}}</${node.component}>`;
  }
  if (hasSingleTextChild) {
    const text = node.children[0].props?.text ?? "";
    return `${pad}<${node.component}${attrs}>${text}</${node.component}>`;
  }
  const bodyLines = renderChildren(node, indent + 2, imports);
  if (VOID_ELEMENTS.has(node.component) && bodyLines === null) {
    return `${pad}<${node.component}${attrs} />`;
  }
  if (bodyLines === null || bodyLines === "") {
    return `${pad}<${node.component}${attrs} />`;
  }
  return [
    `${pad}<${node.component}${attrs}>`,
    bodyLines,
    `${pad}</${node.component}>`
  ].join("\n");
}
function renderChildren(node, indent, imports) {
  const pad = " ".repeat(indent);
  const children = node.children ?? [];
  if (node.iterate) {
    const { source, itemName, keyExpression } = node.iterate;
    return children.map((c) => emitNode(c, indent, imports)).join("\n");
  }
  if (children.length === 0 && !node.expressions?.children) return null;
  if (children.length === 0 && node.expressions?.children) return "";
  return children.map((c) => {
    if (c.iterate) return emitIterated(c, indent, imports);
    return emitNode(c, indent, imports);
  }).join("\n");
}
function emitIterated(node, indent, imports) {
  const pad = " ".repeat(indent);
  const { source, itemName, keyExpression } = node.iterate;
  const inner = emitNode({ ...node, iterate: void 0 }, indent + 2, imports);
  const args = keyExpression ? `(${itemName}, ${keyExpression})` : `(${itemName})`;
  return [
    `${pad}{${source}.map(${args} => (`,
    inner,
    `${pad}))}`
  ].join("\n");
}
function formatAttrParts(props, expressions) {
  const parts = [];
  for (const [k, v] of Object.entries(props ?? {})) {
    if (v === void 0 || v === null) continue;
    parts.push(formatStaticProp(k, v));
  }
  for (const [k, expr] of Object.entries(expressions ?? {})) {
    if (k === "children") continue;
    parts.push(`${k}={${expr}}`);
  }
  return parts;
}
function formatStaticProp(name, value) {
  if (value === true) return name;
  if (typeof value === "string") return `${name}=${JSON.stringify(value)}`;
  if (typeof value === "number" || typeof value === "boolean") {
    return `${name}={${value}}`;
  }
  return `${name}={${JSON.stringify(value)}}`;
}
const VOID_ELEMENTS = /* @__PURE__ */ new Set([
  "area",
  "base",
  "br",
  "col",
  "embed",
  "hr",
  "img",
  "input",
  "link",
  "meta",
  "source",
  "track",
  "wbr"
]);
export {
  emitJsxSource
};
