import importlib
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path


def has_tmux() -> bool:
    try:
        result = subprocess.run(
            ["tmux", "-V"],
            check=False,
            capture_output=True,
            text=True,
        )
    except FileNotFoundError:
        return False
    return result.returncode == 0


class PTYMCPTestCase(unittest.TestCase):
    def setUp(self):
        self._temp_dir = tempfile.mkdtemp(prefix="pty-mcp-tests-")
        self.logs_dir = os.path.join(self._temp_dir, "logs")
        self.capture_dir = os.path.join(self._temp_dir, "capture")
        self.state_dir = os.path.join(self._temp_dir, "state")
        os.makedirs(self.logs_dir, exist_ok=True)
        os.makedirs(self.capture_dir, exist_ok=True)
        os.makedirs(self.state_dir, exist_ok=True)

        self._env_backup = os.environ.copy()
        os.environ.update(
            {
                "PTY_MCP_SESSION_LOG_DIR": self.logs_dir,
                "PTY_MCP_TMUX_CAPTURE_DIR": self.capture_dir,
                "PTY_MCP_STATE_DIR": self.state_dir,
                "PTY_MCP_REQUIRE_OWNER": "1",
                "PTY_MCP_DANGEROUS_LEGACY_MODE": "0",
                "PTY_MCP_ENABLE_ADMIN_TOOLS": "0",
                "PTY_MCP_ENABLE_CONTROL_TOOLS": "0",
            }
        )

        root = Path(__file__).resolve().parents[2]
        src_dir = str(root / "src")
        if src_dir not in sys.path:
            sys.path.insert(0, src_dir)
            self._inserted_src_path = src_dir
        else:
            self._inserted_src_path = None

        self.server = importlib.import_module("pty_mcp.server")
        self.server = importlib.reload(self.server)
        self._reset_runtime_state()

    def tearDown(self):
        try:
            self._cleanup_live_sessions()
        finally:
            self._kill_leftover_tmux_sessions()
            self._restore_environment()
            shutil.rmtree(self._temp_dir, ignore_errors=True)

    def _restore_environment(self):
        os.environ.clear()
        os.environ.update(self._env_backup)
        if self._inserted_src_path and self._inserted_src_path in sys.path:
            sys.path.remove(self._inserted_src_path)

    def _reset_runtime_state(self):
        self.server.sessions.clear()
        self.server.dangerous_confirmations.clear()

    def _cleanup_live_sessions(self):
        for sid, session in list(self.server.sessions.items()):
            self.server.sessions.pop(sid, None)
            try:
                self.server._cleanup_session(sid, session)
            except Exception:
                pass

    def _kill_leftover_tmux_sessions(self):
        if not has_tmux():
            return
        try:
            result = subprocess.run(
                ["tmux", "list-sessions", "-F", "#{session_name}"],
                check=False,
                capture_output=True,
                text=True,
            )
        except FileNotFoundError:
            return
        if result.returncode != 0:
            return
        for line in result.stdout.splitlines():
            name = line.strip()
            if not name.startswith("ptymcp-"):
                continue
            subprocess.run(
                ["tmux", "kill-session", "-t", name],
                check=False,
                capture_output=True,
                text=True,
            )

    def wait_quiet(
        self, session_id, timeout_ms=2000, quiescence_ms=150, client_id=None
    ):
        return self.server.pty_read_quiescent(
            session_id,
            timeout_ms=timeout_ms,
            quiescence_ms=quiescence_ms,
            client_id=client_id,
        )


class TmuxOnlyTestCase(PTYMCPTestCase):
    def setUp(self):
        super().setUp()
        if not has_tmux():
            self.skipTest("tmux is not available")
