"""Tests for create_agent_template utility."""

from pathlib import Path
from unittest.mock import patch

import pytest

from agency_swarm.utils.create_agent_template import create_agent_template


class TestCreateAgentTemplate:
    """Test the create_agent_template function."""

    def test_create_basic_agent_template(self, tmp_path: Path) -> None:
        """Test creating a basic agent template with minimal parameters."""
        agent_name = "Test Agent"

        result = create_agent_template(agent_name=agent_name, path=str(tmp_path))
        assert result is True

        # Check folder structure (now uses underscores)
        agent_folder = tmp_path / "test_agent"
        assert agent_folder.exists()
        assert agent_folder.is_dir()

        # Check required files
        assert (agent_folder / "__init__.py").exists()
        assert (agent_folder / "test_agent.py").exists()
        assert (agent_folder / "instructions.md").exists()

        # Check required directories
        assert (agent_folder / "tools").exists()
        assert (agent_folder / "files").exists()
        assert (agent_folder / "tools" / "__init__.py").exists()
        assert (agent_folder / "tools" / "ExampleTool.py").exists()

    def test_create_agent_template_without_description(self, tmp_path: Path) -> None:
        """Test creating agent template without description - should use default placeholder."""
        agent_name = "Simple Agent"

        assert create_agent_template(agent_name=agent_name, path=str(tmp_path)) is True

        agent_folder = tmp_path / "simple_agent"
        agent_file = agent_folder / "simple_agent.py"
        agent_content = agent_file.read_text(encoding="utf-8")

        # Should NOT have description line
        assert "description=" not in agent_content
        assert f'name="{agent_name}"' in agent_content
        assert 'instructions="./instructions.md"' in agent_content

        # Instructions file should have structured template with placeholder
        instructions_file = agent_folder / "instructions.md"
        instructions_content = instructions_file.read_text(encoding="utf-8")
        assert "# Role" in instructions_content
        assert "**[insert role" in instructions_content
        assert "# Goals" in instructions_content
        assert "# Process" in instructions_content
        assert "# Output Format" in instructions_content
        assert "# Additional Notes" in instructions_content

    def test_agent_file_content_structure(self, tmp_path: Path) -> None:
        """Test that generated agent file has correct v1.x structure."""
        agent_name = "Data Processor"
        agent_description = "Processes and analyzes data"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
            )
            is True
        )

        agent_folder = tmp_path / "data_processor"
        agent_file = agent_folder / "data_processor.py"
        agent_content = agent_file.read_text(encoding="utf-8")

        # Check v1.x imports and structure
        assert "from agency_swarm import Agent, ModelSettings" in agent_content
        assert "data_processor = Agent(" in agent_content
        assert f'name="{agent_name}"' in agent_content
        assert f'description="{agent_description}"' in agent_content
        assert 'instructions="./instructions.md"' in agent_content
        assert 'files_folder="./files"' in agent_content
        assert 'tools_folder="./tools"' in agent_content
        assert 'model="gpt-5.4"' in agent_content  # Updated default model
        assert "ModelSettings(" in agent_content
        # gpt-5.4 is a reasoning model - no temperature
        assert "temperature=" not in agent_content

    def test_instructions_file_content(self, tmp_path: Path) -> None:
        """Test that instructions file has correct structured template content."""
        agent_name = "Research Assistant"
        agent_description = "Helps with research tasks"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
            )
            is True
        )

        agent_folder = tmp_path / "research_assistant"
        instructions_file = agent_folder / "instructions.md"
        instructions_content = instructions_file.read_text(encoding="utf-8")

        # Should have structured template sections
        assert "# Role" in instructions_content
        assert "You are" in instructions_content
        assert agent_description in instructions_content
        assert "# Goals" in instructions_content
        assert "# Process" in instructions_content
        assert "# Output Format" in instructions_content
        assert "# Additional Notes" in instructions_content

    def test_custom_instructions(self, tmp_path: Path) -> None:
        """Test creating agent with custom instructions."""
        agent_name = "Custom Agent"
        agent_description = "Custom description"
        custom_instructions = "These are custom instructions for the agent."

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
                instructions=custom_instructions,
            )
            is True
        )

        agent_folder = tmp_path / "custom_agent"
        instructions_file = agent_folder / "instructions.md"
        instructions_content = instructions_file.read_text(encoding="utf-8")

        assert instructions_content == custom_instructions

    def test_custom_instructions_with_description(self, tmp_path: Path) -> None:
        """Test creating agent with custom instructions and description."""
        agent_name = "Custom Agent"
        agent_description = "Custom description"
        custom_instructions = "You are a specialized agent. Follow these rules: 1. Be precise 2. Be helpful"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                instructions=custom_instructions,
                path=str(tmp_path),
            )
            is True
        )

        agent_folder = tmp_path / "custom_agent"

        # Agent file should have description
        agent_file = agent_folder / "custom_agent.py"
        agent_content = agent_file.read_text(encoding="utf-8")
        assert f'description="{agent_description}"' in agent_content

        # Instructions file should have custom content (not auto-generated)
        instructions_file = agent_folder / "instructions.md"
        instructions_content = instructions_file.read_text(encoding="utf-8")
        assert instructions_content == custom_instructions

    def test_custom_instructions_without_description(self, tmp_path: Path) -> None:
        """Test creating agent with custom instructions but no description."""
        agent_name = "Instruction Agent"
        custom_instructions = "You are a specialized agent with custom instructions."

        assert (
            create_agent_template(agent_name=agent_name, instructions=custom_instructions, path=str(tmp_path)) is True
        )

        agent_folder = tmp_path / "instruction_agent"

        # Agent file should NOT have description
        agent_file = agent_folder / "instruction_agent.py"
        agent_content = agent_file.read_text(encoding="utf-8")
        assert "description=" not in agent_content

        # Instructions file should have custom content
        instructions_file = agent_folder / "instructions.md"
        instructions_content = instructions_file.read_text(encoding="utf-8")
        assert instructions_content == custom_instructions

    def test_use_txt_extension(self, tmp_path: Path) -> None:
        """Test creating agent with .txt instructions file."""
        agent_name = "Text Agent"
        agent_description = "Uses txt files"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
                use_txt=True,
            )
            is True
        )

        agent_folder = tmp_path / "text_agent"

        # Should create .txt file instead of .md
        assert (agent_folder / "instructions.txt").exists()
        assert not (agent_folder / "instructions.md").exists()

        # Agent file should reference .txt extension
        agent_file = agent_folder / "text_agent.py"
        agent_content = agent_file.read_text(encoding="utf-8")
        assert 'instructions="./instructions.txt"' in agent_content

    def test_without_example_tool(self, tmp_path: Path) -> None:
        """Test creating agent without example tool."""
        agent_name = "No Tool Agent"
        agent_description = "Agent without example tool"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
                include_example_tool=False,
            )
            is True
        )

        agent_folder = tmp_path / "no_tool_agent"

        # Should not create ExampleTool.py
        assert not (agent_folder / "tools" / "ExampleTool.py").exists()
        # But should still create tools folder and __init__.py
        assert (agent_folder / "tools").exists()
        assert (agent_folder / "tools" / "__init__.py").exists()

    def test_init_file_content(self, tmp_path: Path) -> None:
        """Test that __init__.py file has correct imports."""
        agent_name = "Import Test Agent"
        agent_description = "Test imports"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
            )
            is True
        )

        agent_folder = tmp_path / "import_test_agent"
        init_file = agent_folder / "__init__.py"
        init_content = init_file.read_text(encoding="utf-8")

        assert "from .import_test_agent import import_test_agent" in init_content

    def test_example_tool_content(self, tmp_path: Path) -> None:
        """Test that ExampleTool.py has correct v1.x structure."""
        agent_name = "Tool Test Agent"
        agent_description = "Test tool generation"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
            )
            is True
        )

        agent_folder = tmp_path / "tool_test_agent"
        tool_file = agent_folder / "tools" / "ExampleTool.py"
        tool_content = tool_file.read_text(encoding="utf-8")

        # Check v1.x tool structure
        assert "from agency_swarm.tools import BaseTool" in tool_content
        assert "from pydantic import Field" in tool_content
        assert "from dotenv import load_dotenv" in tool_content
        assert "load_dotenv()" in tool_content
        assert "class ExampleTool(BaseTool):" in tool_content
        assert "def run(self):" in tool_content
        assert 'if __name__ == "__main__":' in tool_content

    def test_folder_already_exists_error(self, tmp_path: Path) -> None:
        """Test that creating agent in existing folder raises error."""
        agent_name = "Existing Agent"
        agent_description = "Test existing folder"

        # Create the folder first
        (tmp_path / "existing_agent").mkdir()

        # Should raise exception
        with pytest.raises(FileExistsError, match="Folder already exists"):
            create_agent_template(agent_name=agent_name, agent_description=agent_description, path=str(tmp_path))

    def test_agent_name_normalization(self, tmp_path: Path) -> None:
        """Test that agent names with spaces are normalized correctly."""
        agent_name = "Complex Agent Name With Spaces"
        agent_description = "Test name normalization"

        assert (
            create_agent_template(
                agent_name=agent_name,
                agent_description=agent_description,
                path=str(tmp_path),
            )
            is True
        )

        # Should create folder with underscores
        agent_folder = tmp_path / "complex_agent_name_with_spaces"
        assert agent_folder.exists()

        # Check that agent variable is correct in files
        agent_file = agent_folder / "complex_agent_name_with_spaces.py"
        agent_content = agent_file.read_text(encoding="utf-8")
        assert "complex_agent_name_with_spaces = Agent(" in agent_content

        init_file = agent_folder / "__init__.py"
        init_content = init_file.read_text(encoding="utf-8")
        assert "from .complex_agent_name_with_spaces import complex_agent_name_with_spaces" in init_content

    def test_agent_name_with_dots_preserves_version_digits(self, tmp_path: Path) -> None:
        """Agent names containing dots should normalize to underscores without dropping digits."""
        agent_name = "Versioned Agent 1.2"

        assert create_agent_template(agent_name=agent_name, path=str(tmp_path)) is True

        agent_folder = tmp_path / "versioned_agent_1_2"
        assert agent_folder.exists()
        assert (agent_folder / "versioned_agent_1_2.py").exists()

        init_content = (agent_folder / "__init__.py").read_text(encoding="utf-8")
        assert "from .versioned_agent_1_2 import versioned_agent_1_2" in init_content

    @patch("builtins.input")
    def test_interactive_input(self, mock_input, tmp_path: Path) -> None:
        """Test interactive input when name not provided."""
        mock_input.return_value = "Interactive Agent"

        assert create_agent_template(path=str(tmp_path)) is True

        # Should create agent with input name
        agent_folder = tmp_path / "interactive_agent"
        assert agent_folder.exists()

        agent_file = agent_folder / "interactive_agent.py"
        agent_content = agent_file.read_text(encoding="utf-8")
        assert 'name="Interactive Agent"' in agent_content
        # Should NOT have description since we don't prompt for it anymore
        assert "description=" not in agent_content
