from __future__ import annotations

import re
from typing import Any
from uuid import uuid4

from niannian.brain.executive.task_graph import TaskGraph, TaskStep
from niannian.personas import EXECUTIVE

_WORK_GOAL = re.compile(r"帮|改|写|查|修|实现|设计|代码|ppt|docker|pytest", re.I)


class ExecutiveComposer:
    """小谋 · 规则版 TaskGraph 规划。"""

    @staticmethod
    def trace_line(msg: str) -> str:
        return f"[{EXECUTIVE}] {msg}"

    def plan_from_message(self, text: str, policy: Any, *, plan_mode: bool = False) -> TaskGraph | None:
        stripped = text.strip()
        if not stripped:
            return None
        regime = getattr(policy, "regime", "companion")
        if plan_mode:
            light = regime not in ("work", "hybrid") and not _WORK_GOAL.search(stripped)
            return self._build_graph(stripped[:120], light=light)
        if regime not in ("work", "hybrid"):
            return None
        if not _WORK_GOAL.search(stripped):
            return None
        return self._build_graph(stripped[:120], light=False)

    def _build_graph(self, goal: str, *, light: bool) -> TaskGraph:
        if light:
            steps = [
                TaskStep(
                    step_id="understand",
                    label="理解问题",
                    planes=frozenset({"P1", "P3"}),
                    status="running",
                ),
                TaskStep(
                    step_id="respond",
                    label="组织回复",
                    planes=frozenset({"P13", "P14"}),
                ),
            ]
        else:
            steps = [
                TaskStep(
                    step_id="understand",
                    label="理解目标",
                    planes=frozenset({"P1", "P3", "P6"}),
                    status="running",
                ),
                TaskStep(
                    step_id="recall",
                    label="召回相关记忆",
                    planes=frozenset({"P9"}),
                ),
                TaskStep(
                    step_id="act",
                    label="执行或给方案",
                    planes=frozenset({"P12", "P13"}),
                ),
                TaskStep(
                    step_id="respond",
                    label="整理回复",
                    planes=frozenset({"P13", "P14"}),
                ),
            ]
        return TaskGraph(task_id=uuid4().hex[:12], goal=goal, steps=steps)

    def observe_turn(self, graph: TaskGraph, reply: str) -> TaskGraph:
        """turn 成功后推进 step：running→done，下一 pending→running。"""
        del reply  # 规则版不解析 reply 内容
        if not graph.steps:
            return graph
        for step in graph.steps:
            if step.status == "running":
                step.status = "done"
                break
        for step in graph.steps:
            if step.status == "pending":
                step.status = "running"
                break
        return graph
