import json
from pathlib import Path
import structlog

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

logger = structlog.get_logger()


class ArchitectAgent:
    """
    Architect Agent
    职责：项目分析、架构设计、目录规划、数据库设计、接口设计
    """

    SYSTEM_PROMPT = """You are a Senior Software Architect.
Analyze the project and design a complete architecture.

Output a JSON object with:
{
  "overview": "Architecture description",
  "directory_structure": {
    "src/": {
      "main.py": "Entry point",
      "models/": {"user.py": "User model"}
    }
  },
  "database": {
    "type": "postgresql|sqlite|mongodb|none",
    "tables": [
      {"name": "users", "columns": ["id", "email", "created_at"]}
    ]
  },
  "api": {
    "framework": "fastapi|flask|express|none",
    "endpoints": [
      {"method": "GET", "path": "/users", "description": "List users"}
    ]
  },
  "dependencies": ["package1", "package2"],
  "patterns": ["repository", "service", "factory"],
  "notes": "Additional design notes"
}
"""

    def __init__(self):
        self.logger = structlog.get_logger().bind(agent="architect")
        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 design(self, state: EngineeringState) -> dict:
        """设计系统架构"""
        self.logger.info("Architect designing system", request=state["user_request"][:100])

        # Read existing project structure if available
        project_context = self._read_project_context(state.get("sandbox_path") or state.get("repo_path", ""))

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

        prompt = f"""User Request: {state['user_request']}

Project Analysis:
{json.dumps(state.get('project_analysis', {}), indent=2)}

Existing Project Structure:
{project_context}

Design the complete architecture for this project."""

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

        return self._fallback_design(state)

    def _read_project_context(self, path: str, max_files: int = 20) -> str:
        """读取项目现有结构"""
        if not path or not Path(path).exists():
            return "No existing project"

        lines = []
        root = Path(path)
        count = 0
        for f in root.rglob("*"):
            if f.is_file() and count < max_files:
                rel = f.relative_to(root)
                lines.append(str(rel))
                count += 1
        return "\n".join(lines) if lines else "Empty project"

    def _fallback_design(self, state: EngineeringState) -> dict:
        return {
            "overview": f"Architecture for: {state['user_request']}",
            "directory_structure": {"src/": {"main.py": "Entry point"}},
            "database": {"type": "none", "tables": []},
            "api": {"framework": "none", "endpoints": []},
            "dependencies": [],
            "patterns": [],
            "notes": "Fallback design - LLM not available",
        }
