import json
import os
import shlex
from pathlib import Path
from typing import Any

from harbor.agents.installed.base import BaseInstalledAgent, ExecInput
from harbor.models.agent.context import AgentContext
from harbor.models.agent.name import AgentName


class QwenCode(BaseInstalledAgent):
    """
    The QWen Code agent uses Alibaba's QWen Code tool to solve tasks.
    """

    def __init__(self, model_name: str | None = None, *args, **kwargs):
        super().__init__(model_name=model_name, *args, **kwargs)

        # Configurable API settings through agent_kwargs (matching terminal-bench)
        self._api_key = kwargs.get("api_key")
        self._base_url = kwargs.get("base_url")

    @staticmethod
    def name() -> str:
        return AgentName.QWEN_CODE.value

    @property
    def _install_agent_template_path(self) -> Path:
        return Path(__file__).parent / "install-qwen-code.sh.j2"

    def populate_context_post_run(self, context: AgentContext) -> None:
        pass

    def _build_register_mcp_servers_command(self) -> str | None:
        """Return a shell command that writes MCP config to ~/.qwen/settings.json."""
        if not self.mcp_servers:
            return None
        servers: dict[str, dict[str, Any]] = {}
        for server in self.mcp_servers:
            if server.transport == "stdio":
                servers[server.name] = {"command": server.command, "args": server.args}
            elif server.transport == "streamable-http":
                servers[server.name] = {"httpUrl": server.url}
            else:  # sse
                servers[server.name] = {"url": server.url}
        config = json.dumps({"mcpServers": servers}, indent=2)
        escaped = shlex.quote(config)
        return f"mkdir -p ~/.qwen && echo {escaped} > ~/.qwen/settings.json"

    def create_run_agent_commands(self, instruction: str) -> list[ExecInput]:
        escaped_instruction = shlex.quote(instruction)

        env = {}

        # API Key - prefer agent_kwargs over environment variables (matching terminal-bench)
        if self._api_key:
            env["OPENAI_API_KEY"] = self._api_key
        elif "OPENAI_API_KEY" in os.environ:
            env["OPENAI_API_KEY"] = os.environ["OPENAI_API_KEY"]
        # Don't raise error here - API key will be provided via container environment

        # Model - use model_name parameter or fallback (matching terminal-bench)
        if self.model_name:
            env["OPENAI_MODEL"] = self.model_name
        elif "OPENAI_MODEL" in os.environ:
            env["OPENAI_MODEL"] = os.environ["OPENAI_MODEL"]
        else:
            env["OPENAI_MODEL"] = "qwen3-coder-plus"

        # Base URL - prefer agent_kwargs over environment variables (matching terminal-bench)
        if self._base_url:
            env["OPENAI_BASE_URL"] = self._base_url
        elif "OPENAI_BASE_URL" in os.environ:
            env["OPENAI_BASE_URL"] = os.environ["OPENAI_BASE_URL"]
        # Don't set default here - let container environment or qwen CLI handle it

        commands: list[ExecInput] = []

        mcp_command = self._build_register_mcp_servers_command()
        if mcp_command:
            commands.append(ExecInput(command=mcp_command, env=env))

        commands.append(
            ExecInput(
                command=(
                    ". ~/.nvm/nvm.sh; "
                    f"qwen --yolo --prompt={escaped_instruction} "
                    f"2>&1 | stdbuf -oL tee /logs/agent/qwen-code.txt"
                ),
                env=env,
            )
        )

        return commands
