MAX_BODY_CHARS = 24000
MAX_CONTEXT_NOTE_CHARS = 1500


def _build_context_block(context_notes: list[dict]) -> str:
    """Format project context notes into a prompt block."""
    lines = [
        "--- Project Context ---",
        "The following notes are from the same project. Notes tagged 'definition' are "
        "canonical term definitions — treat them as authoritative. Use them to maintain "
        "consistency in terminology, tone, style, and [[wikilinks]] to other documents.",
        "",
    ]
    for n in context_notes:
        tags_str = f"  [tags: {', '.join(n['tags'])}]" if n.get("tags") else ""
        body_preview = (n["body"] or "")[:MAX_CONTEXT_NOTE_CHARS]
        if len(n["body"] or "") > MAX_CONTEXT_NOTE_CHARS:
            body_preview += "…"
        lines.append(f"**{n['title']}**{tags_str}")
        if body_preview:
            lines.append(body_preview)
        lines.append("")
    lines.append("--- End Project Context ---")
    return "\n".join(lines)


def build_assist_messages(
    body: str,
    target_section: str,
    instruction: str,
    whole_doc: bool = False,
    context_notes: list[dict] | None = None,
) -> list[dict]:
    """Build Ollama messages for writing assist.

    When whole_doc=True, the model revises the entire document.
    When whole_doc=False (section mode), the full body is provided as read-only
    context and the model outputs only the replacement for the target section.

    context_notes: optional list of {title, tags, body} dicts from the same project,
    injected so the model can maintain consistency with related documents.
    """
    truncated_body = body[:MAX_BODY_CHARS]
    if len(body) > MAX_BODY_CHARS:
        truncated_body += "\n… (truncated)"

    context_block = (_build_context_block(context_notes) + "\n\n") if context_notes else ""

    if whole_doc:
        system_content = (
            "You are a writing assistant. Revise the document per the instruction. "
            "Output ONLY the complete revised document. Preserve all structure and "
            "content not addressed by the instruction. "
            "Preserve all markdown formatting exactly — including bullet lists (- item), "
            "numbered lists (1. item), nested/indented sub-items (  - sub), bold (**text**), "
            "italic (_text_), and code blocks. Never flatten nested lists into plain text. "
            "When referencing concepts defined in the Project Context, use [[wikilinks]] "
            "to link to the relevant note by its exact title."
        )
        user_content = (
            f"{context_block}"
            f"--- Document ---\n{truncated_body}\n--- End Document ---\n\n"
            f"Instruction: {instruction}"
        )
    else:
        system_content = (
            "You are an AI writing assistant integrated into a note-taking app. "
            "The user is editing a document. The full document is shown below for context.\n\n"
            f"--- Full Document ---\n{truncated_body}\n--- End Document ---\n\n"
            "The user will give you a specific section of the document and an instruction. "
            "Output ONLY the replacement text for that section. "
            "If the target section starts with a markdown heading (e.g. ## Heading), "
            "your output MUST also start with a heading at the same level. "
            "You may revise the heading text but do not remove it. "
            "Do not include other sections, explanatory text, or markdown code fences around the output. "
            "Match the document's existing tone and style. "
            "IMPORTANT: Preserve all markdown formatting exactly — including bullet lists (- item), "
            "numbered lists (1. item), nested/indented sub-items (  - sub), bold (**text**), "
            "italic (_text_), and code blocks. Never flatten nested lists into plain text. "
            "When referencing concepts defined in the Project Context, use [[wikilinks]] "
            "to link to the relevant note by its exact title."
        )
        user_content = (
            f"{context_block}"
            f"--- Target Section ---\n{target_section}\n--- End Target Section ---\n\n"
            f"Instruction: {instruction}"
        )

    return [
        {"role": "system", "content": system_content},
        {"role": "user", "content": user_content},
    ]
