"""Todo/task tracking tool for Promethian.

Provides structured task tracking during execution for better planning
and user visibility.

This is a built-in tool that's always available to the agent.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Literal, Callable
from enum import Enum


class TodoStatus(str, Enum):
    """Status of a todo item."""
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"


@dataclass
class TodoItem:
    """A single todo item."""
    content: str  # What needs to be done (imperative form)
    active_form: str  # Present continuous form for display during execution
    status: TodoStatus = TodoStatus.PENDING

    def to_dict(self) -> dict:
        return {
            "content": self.content,
            "activeForm": self.active_form,
            "status": self.status.value,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "TodoItem":
        return cls(
            content=data["content"],
            active_form=data.get("activeForm", data["content"]),
            status=TodoStatus(data.get("status", "pending")),
        )


@dataclass
class TodoResult:
    """Result from a todo operation."""
    success: bool
    todos: list[TodoItem]
    error: str | None = None


class TodoWriteTool:
    """
    Task tracking tool for execution visibility.

    Features:
    - Track tasks with status (pending, in_progress, completed)
    - Display active task during execution
    - Provide progress visibility to user
    """

    def __init__(
        self,
        on_update: Callable[[list[TodoItem]], None] | None = None,
    ):
        """
        Initialize the todo tool.

        Args:
            on_update: Optional callback when todos are updated
        """
        self._todos: list[TodoItem] = []
        self._on_update = on_update

    @property
    def todos(self) -> list[TodoItem]:
        """Get current todo list."""
        return self._todos.copy()

    @property
    def current_task(self) -> TodoItem | None:
        """Get the currently in-progress task."""
        for todo in self._todos:
            if todo.status == TodoStatus.IN_PROGRESS:
                return todo
        return None

    @property
    def progress(self) -> tuple[int, int]:
        """Get (completed, total) progress."""
        completed = sum(1 for t in self._todos if t.status == TodoStatus.COMPLETED)
        return (completed, len(self._todos))

    async def write(self, todos: list[dict]) -> TodoResult:
        """
        Update the todo list.

        Args:
            todos: List of todo items with content, activeForm, and status

        Returns:
            TodoResult with updated list
        """
        try:
            self._todos = [TodoItem.from_dict(t) for t in todos]

            if self._on_update:
                self._on_update(self._todos)

            return TodoResult(
                success=True,
                todos=self._todos.copy(),
            )

        except Exception as e:
            return TodoResult(
                success=False,
                todos=self._todos.copy(),
                error=str(e),
            )

    def get_display_text(self) -> str:
        """Get formatted display text for the todo list."""
        if not self._todos:
            return ""

        lines = []
        for i, todo in enumerate(self._todos, 1):
            if todo.status == TodoStatus.COMPLETED:
                status_icon = "[x]"
            elif todo.status == TodoStatus.IN_PROGRESS:
                status_icon = "[>]"
            else:
                status_icon = "[ ]"

            lines.append(f"{status_icon} {todo.content}")

        return "\n".join(lines)

    def get_tool_schemas(self) -> list[dict]:
        """Get Claude tool schema for todo_write."""
        return [{
            "name": "todo_write",
            "description": (
                "Track and update tasks during execution. Use this to show progress "
                "and maintain visibility into what you're working on. Each todo has: "
                "content (what to do), activeForm (present tense for display), and status."
            ),
            "input_schema": {
                "type": "object",
                "properties": {
                    "todos": {
                        "type": "array",
                        "description": "The full todo list with all items",
                        "items": {
                            "type": "object",
                            "properties": {
                                "content": {
                                    "type": "string",
                                    "description": "Task description in imperative form (e.g., 'Fix the bug')"
                                },
                                "activeForm": {
                                    "type": "string",
                                    "description": "Task in present continuous (e.g., 'Fixing the bug')"
                                },
                                "status": {
                                    "type": "string",
                                    "enum": ["pending", "in_progress", "completed"],
                                    "description": "Task status"
                                }
                            },
                            "required": ["content", "status", "activeForm"]
                        }
                    }
                },
                "required": ["todos"]
            }
        }]

    async def execute_tool(self, name: str, params: dict) -> TodoResult:
        """Execute the todo tool."""
        if name == "todo_write":
            return await self.write(params.get("todos", []))
        return TodoResult(
            success=False,
            todos=self._todos.copy(),
            error=f"Unknown todo tool: {name}"
        )


# Singleton instance
_todo_tool: TodoWriteTool | None = None


def get_todo_tool(
    on_update: Callable[[list[TodoItem]], None] | None = None,
) -> TodoWriteTool:
    """Get the global todo tool instance."""
    global _todo_tool
    if _todo_tool is None:
        _todo_tool = TodoWriteTool(on_update=on_update)
    return _todo_tool


def reset_todo_tool() -> None:
    """Reset the global todo tool instance."""
    global _todo_tool
    _todo_tool = None
