// Shared Markdown building blocks for the copilot-export module (Demo-067 E,
// KAR-984) — the Markdown counterpart to docx-shared.ts. Every MD builder
// assembles an array of top-level string "blocks" that mirrors the DOCX
// builders' `(Paragraph | Table)[]` children array 1:1 (same order, same
// content, same conditional/empty-state branches) and joins them into one
// string at the end via `joinMdBlocks` — keeps the two formats structurally
// parallel so they can drift on markup syntax only, never on content.
//
// Pure, format-agnostic beyond GFM markup — no DB/network/FS access (ADR 019,
// same discipline as docx-shared.ts). Number/percent formatting is NOT
// duplicated here: MD builders import `formatNumberDe`/`formatPercentDe`
// directly from `./docx-shared` (those two are already plain `Intl` string
// formatters with no `docx` package dependency, so re-importing them costs
// nothing and avoids a second copy to drift).

import type { AiInstructionBlockContent } from './types'

/** Document title — the single H1 per document (DOCX's `docTitle`, TITLE
 * style). */
export function mdTitle(text: string): string {
  return `# ${text}`
}

/** DOCX `heading1` equivalent. */
export function mdH1(text: string): string {
  return `## ${text}`
}

/** DOCX `heading2` equivalent. */
export function mdH2(text: string): string {
  return `### ${text}`
}

/** DOCX `heading3` equivalent. */
export function mdH3(text: string): string {
  return `#### ${text}`
}

export function mdBold(text: string): string {
  return `**${text}**`
}

export function mdItalic(text: string): string {
  return `_${text}_`
}

export function mdBullets(items: readonly string[]): string {
  return items.map((item) => `- ${item}`).join('\n')
}

/** Escape a value for use inside a GFM pipe-table cell — an unescaped `|`
 * would be parsed as a column separator, and a literal newline breaks the
 * row grammar entirely. */
function mdTableCell(value: string): string {
  return value.replace(/\r?\n/g, ' ').replace(/\|/g, '\\|')
}

/** Header-row GFM pipe table — DOCX `dataTable` equivalent. Every row must
 * have the same length as `headers` (same contract as `dataTable`). */
export function mdTable(headers: readonly string[], rows: ReadonlyArray<readonly string[]>): string {
  const headerRow = `| ${headers.map(mdTableCell).join(' | ')} |`
  const separatorRow = `| ${headers.map(() => '---').join(' | ')} |`
  const bodyRows = rows.map((r) => `| ${r.map(mdTableCell).join(' | ')} |`)
  return [headerRow, separatorRow, ...bodyRows].join('\n')
}

/** Label/value ("Steckbrief") table — DOCX `kvTable` equivalent. DOCX's
 * `kvTable` has no header row (it is a 2-column label/value table); GFM pipe
 * tables require one, so this renders a generic `Feld`/`Wert` header (also
 * satisfies "every rendered table has a pipe-table header" for the
 * paste-into-a-chat use case). Same `value || '—'` fallback as `kvTable`'s
 * `new Paragraph(value || '—')`. */
export function mdKvTable(rows: ReadonlyArray<readonly [string, string]>): string {
  return mdTable(
    ['Feld', 'Wert'],
    rows.map(([label, value]) => [label, value || '—'] as const),
  )
}

/** Render the shared AI-instruction block (heading, about-text, usage
 * hints, glossary, optional fictional-data disclaimer) as Markdown blocks.
 * Same content/order as docx-shared.ts's `renderAiInstructionBlock` — the
 * disclaimer (last element) is only present when `content.disclaimer` is
 * non-null, i.e. only for `is_demo` source records (see
 * ai-instruction-block.ts's `fictionalDataDisclaimer`). Rendered as a GFM
 * blockquote — the closest Markdown equivalent of the DOCX version's shaded
 * callout table. */
export function renderAiInstructionBlockMd(content: AiInstructionBlockContent): string[] {
  const blocks: string[] = [
    mdH1(content.heading),
    content.aboutText,
    mdH3(content.usageHeading),
    mdBullets(content.usageHints),
    mdH3(content.glossaryHeading),
    mdTable(
      ['Begriff', 'Definition'],
      content.glossary.map((g) => [g.term, g.definition] as const),
    ),
  ]
  if (content.disclaimer) {
    blocks.push(`> ${mdBold('Demo-Hinweis')}\n>\n> ${content.disclaimer}`)
  }
  return blocks
}

/** Join top-level blocks into the final Markdown document string — one
 * blank line between blocks, single trailing newline. Empty/whitespace-only
 * blocks are dropped rather than leaving a stray blank line (defensive; no
 * current builder pushes one, but block-array assembly across four builders
 * makes an accidental empty string easy to introduce later). The only place
 * in this module that serializes blocks to a string — mirrors docx-
 * shared.ts's `buildDocument` + `packDocumentToBuffer` split. */
export function joinMdBlocks(blocks: readonly string[]): string {
  return blocks.filter((b) => b.trim() !== '').join('\n\n') + '\n'
}
