package docforge

// The neutral document model — the format-independent representation an
// importer produces and an exporter consumes (PRD §3.2). A Markdown
// importer parses source into a Document; the .docx exporter renders a
// Document into OOXML; a future PDF/HTML exporter renders the same
// Document differently. The model carries editable content only —
// placeholders ({{key}}) ride through as literal span text and are
// substituted later by the format exporter's merge pass, exactly as in
// the pre-model pipeline.
//
// Slice 8 (t-paliad-349) lands this model with two real consumers: the
// Markdown importer (pkg/docforge/markdown) and the .docx renderer
// (pkg/docforge/docx), which the shipped submission walker now routes
// through — so there is one parser, not two.

// BlockKind is the logical kind of a block. Its string values are the
// stylemap keys a format exporter looks up (paragraph, heading_1, …), so
// the docx exporter maps Kind → Word paragraph style directly.
type BlockKind string

const (
	KindParagraph    BlockKind = "paragraph"
	KindHeading1     BlockKind = "heading_1"
	KindHeading2     BlockKind = "heading_2"
	KindHeading3     BlockKind = "heading_3"
	KindListBullet   BlockKind = "list_bullet"
	KindListNumbered BlockKind = "list_numbered"
	KindBlockquote   BlockKind = "blockquote"
)

// Document is a sequence of blocks — the whole editable content.
type Document struct {
	Blocks []Block
}

// Block is one paragraph-level unit. Spans is its inline content; an empty
// Spans slice is an intentional empty paragraph (vertical spacing).
type Block struct {
	Kind  BlockKind
	Spans []InlineSpan
}

// InlineSpan is one run of inline content. A span is either:
//   - literal text with optional bold/italic (Link == "", Children nil), or
//   - a hyperlink (Link != "") whose label is the Children spans.
//
// Modelling a link as a span with Children (rather than a per-span Link
// flag) preserves link boundaries: two adjacent links to the same URL stay
// two distinct hyperlink spans, so the exporter emits them byte-identically
// to the pre-model walker.
type InlineSpan struct {
	Text     string
	Bold     bool
	Italic   bool
	Link     string       // non-empty → this span is a hyperlink to Link
	Children []InlineSpan // hyperlink label content (only when Link != "")
}
