"""
quizlib markdown renderer
"""

from typing import TYPE_CHECKING
import re

from quizlib.questions.cloze import Cloze
from quizlib.questions.essay import Essay
from quizlib.questions.multiple_choice import MultipleChoice
from quizlib.questions.true_false import TrueFalse

if TYPE_CHECKING:
    from quizlib.questions.base import Question
    from quizlib.quiz import Quiz


class MarkdownRenderer:
    """Renders quizzes to Markdown format."""

    def render(self, quiz: "Quiz") -> str:
        """Render a quiz to Markdown."""
        parts: list[str] = []

        parts.append(f"# Quiz: {quiz.category}")
        if quiz.info:
            parts.append(f"\n{quiz.info}")

        parts.append("\n---\n")

        for i, question in enumerate(quiz.questions, 1):
            parts.append(self._render_question(question, i))
            parts.append("\n---\n")

        return "\n".join(parts)

    def _render_question(self, question: "Question", index: int) -> str:
        """Render a single question."""
        match question:
            case Essay():
                return self._render_essay(question, index)
            case MultipleChoice():
                return self._render_mc(question, index)
            case TrueFalse():
                return self._render_tf(question, index)
            case Cloze():
                return self._render_cloze(question, index)
            case _:
                raise TypeError(f"Unknown question type: {type(question)}")

    def _render_header(
        self, index: int, name: str, points: float | int | None = None
    ) -> str:
        """Render question header."""
        header = f"## {index}. {name}"
        if points is not None:
            header += f" ({points} Punkte)"
        return header + "\n"

    def _render_essay(self, q: Essay, index: int) -> str:
        parts = [self._render_header(index, q.name, q.defgrade)]
        parts.append(q.name)
        parts.append("\n\n> Antwort:\n")

        for _ in range(q.lines):
            parts.append("> " + "_" * 79 + "\\")
        return "\n".join(parts)

    def _render_mc(self, q: MultipleChoice, index: int) -> str:
        symbol = "( )" if q.is_single else "[ ]"

        lines = [self._render_header(index, q.name, q.defgrade), q.text]
        for _, text in q.answers:
            if text.startswith("```"):
                text = f"&nbsp;\n\n{text}"

            lines.append(f"- {symbol} {text}")

        return "\n".join(lines)

    def _render_tf(self, q: TrueFalse, index: int) -> str:
        parts = [self._render_header(index, q.name)]
        parts.append(q.name + "\n")

        parts.append("- [ ] True")
        parts.append("- [ ] False")

        return "\n".join(parts)

    def _render_cloze(self, q: Cloze, index: int) -> str:
        parts = [self._render_header(index, q.name)]

        # Simplify Cloze syntax: replace {...} with [__________]
        simplified_text = re.sub(r"\{[^}]+\}", "[__________]", q.name)

        parts.append(simplified_text)
        return "\n".join(parts)
