"""Tests for agent management."""

import os
import subprocess
from pathlib import Path

from legionnaire.agent import (
    PIDFILE_NAME,
    AgentStatus,
    AgentType,
    delete_pidfile,
    get_agent_status,
    kill_agent_if_running,
    launch_command,
    pid_alive,
    pidfile_path,
    read_pid,
)


class TestPidfilePath:
    """Tests for pidfile_path function."""

    def test_returns_correct_path(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        result = pidfile_path(worktree)
        assert result == worktree / PIDFILE_NAME


class TestReadPid:
    """Tests for read_pid function."""

    def test_returns_pid_from_file(self, tmp_path: Path):
        pidfile = tmp_path / ".legion-agent.pid"
        pidfile.write_text("12345")

        result = read_pid(pidfile)
        assert result == 12345

    def test_returns_none_for_missing_file(self, tmp_path: Path):
        pidfile = tmp_path / "nonexistent.pid"

        result = read_pid(pidfile)
        assert result is None

    def test_returns_none_for_invalid_content(self, tmp_path: Path):
        pidfile = tmp_path / ".legion-agent.pid"
        pidfile.write_text("not a number")

        result = read_pid(pidfile)
        assert result is None

    def test_handles_whitespace(self, tmp_path: Path):
        pidfile = tmp_path / ".legion-agent.pid"
        pidfile.write_text("  12345  \n")

        result = read_pid(pidfile)
        assert result == 12345


class TestPidAlive:
    """Tests for pid_alive function."""

    def test_current_process_alive(self):
        assert pid_alive(os.getpid()) is True

    def test_nonexistent_pid(self):
        # Use a very high PID that's unlikely to exist
        assert pid_alive(999999999) is False


class TestGetAgentStatus:
    """Tests for get_agent_status function."""

    def test_unknown_when_no_pidfile(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        status, pid = get_agent_status(worktree)
        assert status == AgentStatus.UNKNOWN
        assert pid is None

    def test_running_when_pid_alive(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        # Write current process PID
        pidfile = worktree / PIDFILE_NAME
        pidfile.write_text(str(os.getpid()))

        status, pid = get_agent_status(worktree)
        assert status == AgentStatus.RUNNING
        assert pid == os.getpid()

    def test_stopped_when_pid_dead(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        # Write a PID that doesn't exist
        pidfile = worktree / PIDFILE_NAME
        pidfile.write_text("999999999")

        status, pid = get_agent_status(worktree)
        assert status == AgentStatus.STOPPED
        assert pid == 999999999


class TestLaunchCommand:
    """Tests for launch_command function."""

    def test_claude_command(self, tmp_path: Path):
        worktree = tmp_path / "child"
        cmd = launch_command(AgentType.CLAUDE, "parent-id", "child-id", worktree)

        assert f"cd {worktree}" in cmd
        assert 'LEGION_AGENT_NAME="parent-id/child-id"' in cmd
        assert f"echo $$ > {PIDFILE_NAME}" in cmd
        assert "exec claude" in cmd
        assert "bash -lc" in cmd

    def test_cursor_command(self, tmp_path: Path):
        worktree = tmp_path / "child"
        cmd = launch_command(AgentType.CURSOR, "parent-id", "child-id", worktree)

        assert f"cd {worktree}" in cmd
        assert 'LEGION_AGENT_NAME="parent-id/child-id"' in cmd
        assert f"echo $$ > {PIDFILE_NAME}" in cmd
        assert "exec cursor agent" in cmd
        assert "bash -lc" in cmd

    def test_handles_slashes_in_ids(self, tmp_path: Path):
        worktree = tmp_path / "child"
        cmd = launch_command(AgentType.CLAUDE, "team/feature", "task", worktree)

        assert 'LEGION_AGENT_NAME="team/feature/task"' in cmd


class TestKillAgentIfRunning:
    """Tests for kill_agent_if_running function."""

    def test_returns_false_when_no_pidfile(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        result = kill_agent_if_running(worktree)
        assert result is False

    def test_returns_false_when_pid_dead(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        pidfile = worktree / PIDFILE_NAME
        pidfile.write_text("999999999")

        result = kill_agent_if_running(worktree)
        assert result is False
        # PID file should be cleaned up
        assert not pidfile.exists()

    def test_kills_running_process(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        # Start a sleep process
        proc = subprocess.Popen(["sleep", "60"])
        pidfile = worktree / PIDFILE_NAME
        pidfile.write_text(str(proc.pid))

        result = kill_agent_if_running(worktree, timeout=1.0)

        assert result is True
        assert not pidfile.exists()
        # Process should be terminated
        proc.wait(timeout=1)


class TestDeletePidfile:
    """Tests for delete_pidfile function."""

    def test_deletes_existing_file(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()
        pidfile = worktree / PIDFILE_NAME
        pidfile.write_text("12345")

        delete_pidfile(worktree)
        assert not pidfile.exists()

    def test_no_error_when_missing(self, tmp_path: Path):
        worktree = tmp_path / "child"
        worktree.mkdir()

        delete_pidfile(worktree)  # Should not raise
