# -*- coding: utf-8 -*-
"""
任务清单工具
让 LLM 在终端展示带进度的任务列表，给用户视觉反馈。
"""
import click
from typing import Any, Dict, List

from .base import Tool, coerce_list_of_dicts


_STATUS_ICONS = {
    "pending":     ("○", "\033[2m"),
    "in_progress": ("◐", "\033[33m"),
    "completed":   ("✓", "\033[32m"),
}

_STATUS_ORDER = {"in_progress": 0, "pending": 1, "completed": 2}

# 模块级状态：最近一次 todo_write 的列表。供 main.py 注入到 LLM 上下文，
# 让 LLM 始终能看到当前任务进度，避免"有头无尾"。
# 简单任务不调用 todo_write → 这里为空 → 不注入 → 零 token 浪费。
_last_todos: List[Dict[str, str]] = []


def get_active_todos() -> List[Dict[str, str]]:
    """返回当前 todo 列表的浅拷贝。供 main.py 在 API 调用前注入上下文。"""
    return [dict(t) for t in _last_todos]


def clear_todos() -> None:
    """清空当前 todo 状态。在 /clear 或新建 session 时调用，避免跨会话残留。"""
    global _last_todos
    _last_todos = []


def _render_todos_ui(title: str, sorted_todos: List[Dict[str, str]]):
    """根据当前主题渲染 todo box（Hacker → 方案4 PLAN/UPDATE 风格，Default → 原样）。"""
    try:
        from abyss.ui import get_current_renderer
        from abyss.ui.renderer import HackerRenderer
        R = get_current_renderer()
        if isinstance(R, HackerRenderer):
            # HackerRenderer.todo_box 自动根据完成进度把 title 改 PLAN / PLAN UPDATE
            # 把原 status (in_progress/pending/completed) 转成 renderer 要的 STATUS 样式
            items_for_render = []
            for t in sorted_todos:
                s = (t.get("status") or "pending").lower()
                if s == "completed":
                    rs = "done"
                elif s == "in_progress":
                    rs = "in_progress"
                else:
                    rs = "pending"
                # 传 todo 原字段：content, status, priority, id
                item = {
                    "content": t.get("content", ""),
                    "status": rs,
                    "priority": t.get("priority", "medium"),
                    "id": t.get("id"),
                }
                items_for_render.append(item)
            # title 传进去，todo_box 会把默认中文替换成 PLAN / PLAN UPDATE
            rendered = R.todo_box(title, items_for_render)
            click.echo(rendered, nl=False)
            return
    except Exception:
        pass
    # Default 主题：保持原字符完全一致
    click.echo()
    click.echo(f"  \033[1m{title}\033[0m")
    for t in sorted_todos:
        status = t.get("status", "pending")
        icon, color = _STATUS_ICONS.get(status, ("○", "\033[2m"))
        content = t.get("content", "")
        click.echo(f"    {color}{icon} {content}\033[0m")
    click.echo()


class TodoWriteTool(Tool):
    """任务清单工具：在终端展示格式化的任务列表。

    LLM 在复杂任务（3+ 步骤）开始前调用此工具展示计划，
    完成步骤后再次调用更新状态。工具只负责渲染输出，不维护状态。
    """

    @property
    def name(self) -> str:
        return "todo_write"

    @property
    def description(self) -> str:
        return (
            "在终端展示带进度的任务清单，供用户查看当前任务进展。"
            "适用于复杂任务（3+ 步骤）：开始前调用展示计划，每完成一步后调用更新状态。"
            "merge=false 表示替换整个列表，merge=true 表示合并更新（按 id 匹配）。"
        )

    @property
    def parameters(self) -> Dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "todos": {
                    "type": "array",
                    "description": "任务列表，每项含 id/content/status/priority",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "唯一标识符"
                            },
                            "content": {
                                "type": "string",
                                "description": "任务描述"
                            },
                            "status": {
                                "type": "string",
                                "description": "状态",
                                "enum": ["pending", "in_progress", "completed"]
                            },
                            "priority": {
                                "type": "string",
                                "description": "优先级",
                                "enum": ["high", "medium", "low"]
                            }
                        },
                        "required": ["id", "content", "status", "priority"]
                    },
                    "minItems": 1
                },
                "merge": {
                    "type": "boolean",
                    "description": "true=合并更新现有列表（按id匹配），false=替换整个列表",
                    "default": False
                }
            },
            "required": ["todos", "merge"]
        }

    def execute(self, todos: List[Dict[str, str]], merge: bool = False) -> Dict[str, Any]:
        """渲染任务清单到终端

        Args:
            todos: 任务列表
            merge: 是否合并模式（当前仅影响显示标题措辞）

        Returns:
            {"success": True}
        """
        # 兼容 LLM 将 todos 序列化为 JSON 字符串的情形
        todos = coerce_list_of_dicts(todos)

        if not todos:
            return {"success": False, "error": "任务列表不能为空"}

        # 按状态排序：in_progress > pending > completed
        sorted_todos = sorted(todos, key=lambda t: _STATUS_ORDER.get(t.get("status", "pending"), 99))

        title = "任务进度 (更新)" if merge else "任务计划"
        _render_todos_ui(title, sorted_todos)

        # 更新模块级状态：供 main.py 在后续 API 调用前注入到 system 消息，
        # 让 LLM 始终看到当前任务进度。replace 模式直接替换，merge 模式按 id 合并。
        # 注意：拷贝传入的 dict，避免外部修改影响内部状态。
        global _last_todos
        if merge:
            existing = {t.get("id"): dict(t) for t in _last_todos}
            for t in todos:
                existing[t.get("id")] = dict(t)
            _last_todos = list(existing.values())
        else:
            _last_todos = [dict(t) for t in todos]

        return {"success": True}
