from __future__ import annotations

import os
import subprocess


class AcpxError(Exception):
    """acpx CLI 调用失败时抛出"""
    pass


def create_session(
    agent: str,
    session_name: str,
    cwd: str,
    acpx_binary: str = "acpx",
) -> None:
    """执行: acpx <agent> sessions new --name <session_name>"""
    cmd = [acpx_binary, agent, "sessions", "new", "--name", session_name]
    _run(cmd, acpx_binary, cwd=cwd)


_PROMPT_WRAPPER = """\
You are team member '{name}' on team '{team_name}'.

You have MCP tools from the claude-teams server for team coordination:
- read_inbox(team_name="{team_name}", agent_name="{name}") - Check for new messages
- send_message(team_name="{team_name}", type="message", sender="{name}", recipient="team-lead", content="...", summary="...") - Message teammates
- task_list(team_name="{team_name}") - View team tasks
- task_update(team_name="{team_name}", task_id="...", status="...") - Update task status
- task_get(team_name="{team_name}", task_id="...") - Get task details

Start by reading your inbox for instructions.
When you finish your task, always report back to team-lead using send_message with your result.
After reporting, read your inbox again to check if team-lead has follow-up instructions before finishing.

---

{prompt}"""


def send_prompt(
    agent: str,
    session_name: str,
    prompt: str,
    name: str,
    team_name: str,
    cwd: str,
    acpx_binary: str = "acpx",
) -> None:
    """发送 prompt 给 agent session，自动用 _PROMPT_WRAPPER 包装防止上下文遗忘。
    - session running：加 --no-wait 立即返回，不阻塞
    - session dead/其他：不加 --no-wait，同步等待 agent 启动（需要唤醒），3s 超时视为成功
    """
    prompt = _PROMPT_WRAPPER.format(name=name, team_name=team_name, prompt=prompt)

    status = get_session_status(agent, session_name, cwd, acpx_binary=acpx_binary)
    if status in ("running", "alive"):
        cmd = [acpx_binary, '--approve-all', agent, "--no-wait", "-s", session_name, prompt]
        _run(cmd, acpx_binary, cwd=cwd)
    else:
        cmd = [acpx_binary, '--approve-all', agent, "-s", session_name, prompt]
        # 异步启动，不阻塞：session 处于 dead 状态时需要唤醒，无需等待结果
        _run_detached(cmd, acpx_binary, cwd=cwd)


def close_session(
    agent: str,
    session_name: str,
    cwd: str,
    acpx_binary: str = "acpx",
) -> None:
    """执行: acpx <agent> sessions close <session_name>"""
    cmd = [acpx_binary, agent, "sessions", "close", session_name]
    _run(cmd, acpx_binary, cwd=cwd)


def get_session_status(
    agent: str,
    session_name: str,
    cwd: str,
    acpx_binary: str = "acpx",
) -> str:
    """执行: acpx <agent> status -s <session_name>，返回状态字符串"""
    cmd = [acpx_binary, agent, "status", "-s", session_name]
    result = _run(cmd, acpx_binary, cwd=cwd)
    # 从多行输出中提取 "status: <value>" 那行
    for line in result.stdout.splitlines():
        line = line.strip()
        if line.startswith("status:"):
            return line.split(":", 1)[1].strip()
    return result.stdout.strip()


def _run_detached(
    cmd: list[str],
    acpx_binary: str,
    cwd: str = "",
) -> None:
    """异步启动命令，不等待结果（fire-and-forget）。"""
    try:
        subprocess.Popen(
            cmd,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            stdin=subprocess.DEVNULL,
            cwd=cwd or None,
            start_new_session=True,
        )
    except FileNotFoundError as e:
        raise AcpxError(
            f"acpx binary not found: '{acpx_binary}' is not installed or not in PATH\n"
            f"subprocess PATH: {os.environ.get('PATH', 'N/A')[:300]}\n"
            f"original error: {e}"
        )


def _run(
    cmd: list[str],
    acpx_binary: str,
    timeout: int = 120,
    cwd: str = "",
    timeout_is_success: bool = True,
) -> subprocess.CompletedProcess:
    """执行命令，处理错误情况。timeout_is_success=True 时超时视为成功。"""
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=timeout,
            cwd=cwd,
            stdin=subprocess.DEVNULL,
        )
    except FileNotFoundError as e:
        raise AcpxError(
            f"acpx binary not found: '{acpx_binary}' is not installed or not in PATH\n"
            f"subprocess PATH: {os.environ.get('PATH', 'N/A')[:300]}\n"
            f"original error: {e}"
        )
    except subprocess.TimeoutExpired:
        if timeout_is_success:
            return subprocess.CompletedProcess(cmd, returncode=0, stdout="", stderr="")
        raise AcpxError(f"acpx command timed out after {timeout}s: {' '.join(cmd)}")
    if result.returncode != 0:
        raise AcpxError(result.stderr)
    return result
