"""Task list editor widget."""

from __future__ import annotations

import re
from typing import TYPE_CHECKING

from textual.app import ComposeResult
from textual.events import Click
from textual.message import Message
from textual.widgets import Static

from ganban.ui.confirm import ConfirmButton
from ganban.ui.constants import ICON_CHECKED, ICON_UNCHECKED
from ganban.ui.edit.editable import EditableText
from ganban.ui.edit.editors import TextEditor
from ganban.ui.edit.section import BulletListEditor, ItemRow
from ganban.ui.edit.viewers import MarkdownViewer

if TYPE_CHECKING:
    pass

# Matches: "- [ ] task text" or "- [x] task text" (also *, +)
# Groups: (1) bullet prefix "- ", (2) checkbox char " " or "x"/"X", (3) task text
_TASK_RE = re.compile(r"^([\-\*\+]\s+)\[([ xX])\]\s*(.*)", re.DOTALL)


def _parse_task(item: str) -> tuple[bool, str, str]:
    """Parse a task item into (checked, bullet_prefix, task_text).

    Returns (False, "", full_item) if no checkbox found.
    """
    match = _TASK_RE.match(item)
    if match:
        return match.group(2) in "xX", match.group(1), match.group(3)
    return False, "", item


class TaskCheckbox(Static):
    """Clickable checkbox indicator for a task."""

    class Toggled(Message):
        """Emitted when the checkbox is clicked."""

        @property
        def control(self) -> TaskCheckbox:
            return self._sender

    def __init__(self, checked: bool, **kwargs) -> None:
        super().__init__(ICON_CHECKED if checked else ICON_UNCHECKED, **kwargs)
        self.checked = checked

    def on_click(self, event: Click) -> None:
        event.stop()
        self.checked = not self.checked
        self.update(ICON_CHECKED if self.checked else ICON_UNCHECKED)
        self.post_message(self.Toggled())


class TaskRow(ItemRow):
    """A single task in the task list."""

    def __init__(self, item: str, index: int, parser_factory=None, **kwargs) -> None:
        super().__init__(index, **kwargs)
        self._item = item
        self._parser_factory = parser_factory

    def compose(self) -> ComposeResult:
        checked, _, task_text = _parse_task(self._item)
        yield TaskCheckbox(checked, classes="task-checkbox")
        yield EditableText(
            task_text,
            MarkdownViewer(task_text, parser_factory=self._parser_factory),
            TextEditor(),
            classes="task-text",
            clean=False,
        )
        yield ConfirmButton(classes="task-delete")


class TasksEditor(BulletListEditor):
    """Editor for task list sections using bullet-list extraction."""

    _list_class = "tasks-list"
    _add_class = "add-task"
    _add_placeholder = "+ task"
    _before_class = "tasks-before"
    _after_class = "tasks-after"

    def _make_row(self, item: str, index: int) -> TaskRow:
        return TaskRow(item, index, parser_factory=self._parser_factory, classes="task-row")

    def _format_new_item(self, text: str) -> str:
        return f"- [ ] {text}"

    def _format_edited_item(self, index: int, new_text: str) -> str:
        checked, bullet_prefix, _ = _parse_task(self._extracted.items[index])
        checkbox = "[x]" if checked else "[ ]"
        return f"{bullet_prefix}{checkbox} {new_text}"

    def on_task_checkbox_toggled(self, event: TaskCheckbox.Toggled) -> None:
        event.stop()
        row = event.control.parent
        if isinstance(row, TaskRow):
            _, bullet_prefix, task_text = _parse_task(self._extracted.items[row._index])
            checkbox = "[x]" if event.control.checked else "[ ]"
            self._extracted.items[row._index] = f"{bullet_prefix}{checkbox} {task_text}"
            self._rebuild_body()
