import subprocess
from pathlib import Path
from langgraph.graph import StateGraph, END
from app.state import EngineeringState
from app.executors.claude_executor import run_claude
from app.tools.sandbox import create_sandbox



def prepare_sandbox(state: EngineeringState):
    sandbox_path = create_sandbox(state["repo_path"])
    state["sandbox_path"] = sandbox_path
    state["repo_path"] = sandbox_path
    state["status"] = "sandbox_ready"
    return state


def review_project(state: EngineeringState):
    state["selected_executor"] = "claude"
    state["plan"] = [
        "分析项目结构",
        "定位相关文件",
        "生成建议",
    ]
    state["status"] = "reviewed"
    return state


def execute_code(state: EngineeringState):
    state["code_result"] = run_claude(
        state["repo_path"],
        state["user_request"]
    )

    state["status"] = "code_done"
    return state




def route_after_execute(state: EngineeringState):

    if state["code_result"].get("returncode") == 0:

        return "run_tests"

    return "generate_report"





def run_tests(state: EngineeringState):
    repo = Path(state["repo_path"]).resolve()

    test_commands = [
        ["pytest"],
        ["python", "-m", "pytest"],
        ["python3", "-m", "pytest"],
        ["npm", "test"],
        ["pnpm", "test"],
    ]

    for cmd in test_commands:
        try:
            result = subprocess.run(
                cmd,
                cwd=repo,
                text=True,
                capture_output=True,
                timeout=900,
            )

            if result.returncode == 0:
                state["test_result"] = {
                    "passed": True,
                    "command": " ".join(cmd),
                    "stdout": result.stdout[-8000:],
                    "stderr": result.stderr[-4000:],
                }
                state["status"] = "tests_passed"
                return state

        except FileNotFoundError:
            continue
        except subprocess.TimeoutExpired:
            state["test_result"] = {
                "passed": False,
                "command": " ".join(cmd),
                "message": "测试超时",
            }
            state["status"] = "tests_failed"
            return state

    state["test_result"] = {
        "passed": False,
        "command": "N/A",
        "message": "没有找到可用测试命令，或所有测试命令均失败",
    }
    state["status"] = "tests_failed"
    return state


def generate_report(state: EngineeringState):
    state["report"] = f"""
AI Engineering Report

Request:
{state["user_request"]}

Executor:
{state["selected_executor"]}

Status:
{state["status"]}

Claude Output:

{state["code_result"].get("stdout", "")}

Claude Error:

{state["code_result"].get("stderr", "")}
"""

    return state


def build_graph():
    graph = StateGraph(EngineeringState)

    graph.add_node("prepare_sandbox", prepare_sandbox)
    graph.add_node("review_project", review_project)
    graph.add_node("execute_code", execute_code)
    graph.add_node("run_tests", run_tests)
    graph.add_node("generate_report", generate_report)

    graph.set_entry_point("prepare_sandbox")

    graph.add_edge("prepare_sandbox", "review_project")
    graph.add_edge("review_project", "execute_code")
    graph.add_conditional_edges(
        "execute_code",
        route_after_execute,
        {
            "run_tests": "run_tests",
            "generate_report": "generate_report",
        },
    )
    graph.add_edge("run_tests", "generate_report")
    graph.add_edge("generate_report", END)

    return graph.compile()
