"""Tests for ievo remove command."""

from __future__ import annotations

from pathlib import Path
from unittest.mock import patch

import pytest
import typer
import yaml

from ievo.commands.remove import remove


def test_remove_nonexistent_agent(tmp_project_with_agent: Path) -> None:
    with (
        patch("ievo.commands.remove.require_project", return_value=tmp_project_with_agent),
        pytest.raises(typer.Exit),
    ):
        remove(agent="nonexistent", force=True)


def test_remove_agent_force(tmp_project_with_agent: Path) -> None:
    root = tmp_project_with_agent

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)

    # Agent dir should be removed
    assert not (root / "agents" / "spec-writer").exists()

    # Manifest should be updated
    manifest = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    assert "spec-writer" not in manifest.get("agents", {})


def test_remove_checks_dependents(tmp_project_with_agent: Path) -> None:
    root = tmp_project_with_agent

    # Add architect that depends on spec-writer
    manifest = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    manifest["agents"]["architect"] = "0.1.0"
    (root / ".ievo/manifest.yaml").write_text(yaml.dump(manifest, sort_keys=False))

    arch_dir = root / "agents" / "architect"
    arch_dir.mkdir(parents=True)
    (arch_dir / "agent.yaml").write_text(
        yaml.dump(
            {
                "name": "architect",
                "dependencies": ["spec-writer"],
            },
            sort_keys=False,
        )
    )

    with patch("ievo.commands.remove.require_project", return_value=root):
        # Without --force should raise
        with pytest.raises(typer.Exit):
            remove(agent="spec-writer", force=False)

        # With --force should succeed
        remove(agent="spec-writer", force=True)
        assert not (root / "agents" / "spec-writer").exists()


def test_remove_confirm_yes(tmp_project_with_agent: Path) -> None:
    root = tmp_project_with_agent

    with (
        patch("ievo.commands.remove.require_project", return_value=root),
        patch("ievo.commands.remove.typer.confirm", return_value=True),
    ):
        remove(agent="spec-writer", force=False)
        assert not (root / "agents" / "spec-writer").exists()


def test_remove_confirm_no(tmp_project_with_agent: Path) -> None:
    root = tmp_project_with_agent

    with (
        patch("ievo.commands.remove.require_project", return_value=root),
        patch("ievo.commands.remove.typer.confirm", return_value=False),
        pytest.raises(typer.Exit),
    ):
        remove(agent="spec-writer", force=False)


def test_remove_agent_dir_already_gone(tmp_project_with_agent: Path) -> None:
    """Agent is in manifest but dir was already deleted."""
    import shutil

    root = tmp_project_with_agent
    shutil.rmtree(root / "agents" / "spec-writer")

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)
    manifest = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    assert "spec-writer" not in manifest.get("agents", {})


def test_remove_other_agent_no_yaml(tmp_project_with_agent: Path) -> None:
    """Other agent without agent.yaml doesn't block removal."""
    root = tmp_project_with_agent
    manifest_data = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    manifest_data["agents"]["architect"] = "0.1.0"
    (root / ".ievo/manifest.yaml").write_text(yaml.dump(manifest_data, sort_keys=False))
    # architect dir exists but has no agent.yaml
    (root / "agents" / "architect").mkdir(parents=True)

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)
    assert not (root / "agents" / "spec-writer").exists()


def test_remove_shows_deprecation_warning(tmp_project_with_agent: Path) -> None:
    root = tmp_project_with_agent

    with (
        patch("ievo.commands.remove.require_project", return_value=root),
        patch("ievo.utils.deprecation.warn") as mock_warn,
    ):
        remove(agent="spec-writer", force=True)

    mock_warn.assert_called_once()
    msg = mock_warn.call_args[0][0]
    assert "deprecated" in msg


def test_remove_other_agent_dep_not_matching(tmp_project_with_agent: Path) -> None:
    """Other agent has deps but none match the agent being removed."""
    root = tmp_project_with_agent
    manifest_data = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    manifest_data["agents"]["architect"] = "0.1.0"
    (root / ".ievo/manifest.yaml").write_text(yaml.dump(manifest_data, sort_keys=False))
    arch_dir = root / "agents" / "architect"
    arch_dir.mkdir(parents=True)
    (arch_dir / "agent.yaml").write_text(
        yaml.dump({"name": "architect", "dependencies": ["coder"]}, sort_keys=False)
    )

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)
    assert not (root / "agents" / "spec-writer").exists()


# ── .claude/agents/<name>.md removal tests ──────────────────


def test_remove_deletes_claude_agents_md(tmp_project_with_agent: Path) -> None:
    """Remove deletes .claude/agents/<name>.md file."""
    root = tmp_project_with_agent
    claude_md = root / ".claude" / "agents" / "spec-writer.md"
    assert claude_md.exists()

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)

    assert not claude_md.exists()


def test_remove_deletes_both_formats(tmp_project_with_agent: Path) -> None:
    """Remove cleans up both legacy dir and new .md file."""
    root = tmp_project_with_agent
    legacy_dir = root / "agents" / "spec-writer"
    claude_md = root / ".claude" / "agents" / "spec-writer.md"
    assert legacy_dir.exists()
    assert claude_md.exists()

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)

    assert not legacy_dir.exists()
    assert not claude_md.exists()


def test_remove_md_only(tmp_project_with_agent: Path) -> None:
    """Remove works when only .claude/agents/<name>.md exists (no legacy dir)."""
    import shutil

    root = tmp_project_with_agent
    shutil.rmtree(root / "agents" / "spec-writer")
    claude_md = root / ".claude" / "agents" / "spec-writer.md"
    assert claude_md.exists()

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)

    assert not claude_md.exists()
    manifest = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    assert "spec-writer" not in manifest.get("agents", {})


def test_remove_legacy_only(tmp_project_with_agent: Path) -> None:
    """Remove works when only legacy dir exists (no .claude/agents/ file)."""
    root = tmp_project_with_agent
    (root / ".claude" / "agents" / "spec-writer.md").unlink()

    with patch("ievo.commands.remove.require_project", return_value=root):
        remove(agent="spec-writer", force=True)

    assert not (root / "agents" / "spec-writer").exists()
    manifest = yaml.safe_load((root / ".ievo/manifest.yaml").read_text())
    assert "spec-writer" not in manifest.get("agents", {})
