import json
from typing import Optional
import structlog

from app.configs import settings
from app.state import EngineeringState

logger = structlog.get_logger()


class SupervisorAgent:
    """
    Supervisor Agent
    职责：任务拆解、Agent 分配、流程控制、失败重试
    """

    SYSTEM_PROMPT = """You are the Supervisor of an AI Engineering team.
Your job is to:
1. Analyze the user's request
2. Break it down into concrete engineering tasks
3. Assign tasks to the right agents (Architect, Developer, Tester, Reviewer)
4. Coordinate the workflow

Output a JSON object with:
{
  "project_summary": "Brief description of what needs to be built",
  "complexity": "low | medium | high",
  "tasks": [
    {"id": "1", "title": "...", "agent": "architect|developer|tester|reviewer", "description": "..."}
  ],
  "requires_architecture": true/false,
  "estimated_files": ["file1.py", "file2.py"],
  "tech_stack": ["python", "fastapi", ...]
}
"""

    def __init__(self):
        self.logger = structlog.get_logger().bind(agent="supervisor")
        self._setup_llm()

    def _setup_llm(self):
        try:
            import anthropic
            self.client = anthropic.Anthropic(api_key=settings.anthropic_api_key)
            self.model = "claude-opus-4-5"
        except ImportError:
            self.client = None

    def analyze(self, state: EngineeringState) -> dict:
        """分析用户需求，返回任务列表"""
        self.logger.info("Supervisor analyzing request", request=state["user_request"][:100])

        if not self.client:
            return self._fallback_analysis(state)

        try:
            response = self.client.messages.create(
                model=self.model,
                max_tokens=4096,
                system=self.SYSTEM_PROMPT,
                messages=[{"role": "user", "content": state["user_request"]}],
            )
            text = response.content[0].text
            # Extract JSON from response
            start = text.find("{")
            end = text.rfind("}") + 1
            if start >= 0:
                return json.loads(text[start:end])
        except Exception as e:
            self.logger.warning("Supervisor LLM call failed", error=str(e))

        return self._fallback_analysis(state)

    def _fallback_analysis(self, state: EngineeringState) -> dict:
        return {
            "project_summary": state["user_request"],
            "complexity": "medium",
            "tasks": [
                {"id": "1", "title": "Architecture Design", "agent": "architect", "description": "Design the system architecture"},
                {"id": "2", "title": "Implementation", "agent": "developer", "description": state["user_request"]},
                {"id": "3", "title": "Testing", "agent": "tester", "description": "Write and run tests"},
                {"id": "4", "title": "Code Review", "agent": "reviewer", "description": "Review code quality"},
            ],
            "requires_architecture": True,
            "estimated_files": [],
            "tech_stack": [],
        }

    def should_retry(self, state: EngineeringState) -> bool:
        return (
            state.get("status") in ("failed", "test_failed")
            and state.get("attempts", 0) < state.get("max_attempts", 3)
        )

    def select_executor(self, state: EngineeringState) -> str:
        """选择最合适的执行器"""
        requested = state.get("selected_executor", settings.default_executor)
        return requested if requested in ("claude", "codex", "openhands", "gemini") else "claude"
