import pytest
from fastapi.testclient import TestClient


@pytest.mark.integration
class TestToolTypesAPIExtended:
    """Integration tests for tool types API with new fields."""

    def test_create_tool_type_with_dockerfile(
        self, authenticated_client: TestClient
    ) -> None:
        """Test creating a tool type with dockerfile definition."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "dockerfile-tool",
                "display_name": "Dockerfile Tool",
                "category": "utility",
                "interfaces": ["terminal"],
                "default_port": 8080,
                "definition_type": "dockerfile",
                "dockerfile_template": "FROM python:3.11\nRUN pip install flask",
                "required_variables": [],
            },
        )
        assert response.status_code == 201
        data = response.json()
        assert data["name"] == "dockerfile-tool"
        assert data["definition_type"] == "dockerfile"
        assert data["dockerfile_template"] == "FROM python:3.11\nRUN pip install flask"

    def test_create_tool_type_with_readiness_probe(
        self, authenticated_client: TestClient
    ) -> None:
        """Test creating a tool type with readiness probe."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "probed-tool",
                "display_name": "Probed Tool",
                "category": "utility",
                "interfaces": ["web"],
                "default_port": 8080,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx\n    ports:\n      - '8080:8080'",
                "readiness_probe": {
                    "command": "curl -f http://localhost:8080",
                    "timeout": 30,
                    "interval": 2,
                },
                "required_variables": [],
            },
        )
        assert response.status_code == 201
        data = response.json()
        assert data["readiness_probe"]["command"] == "curl -f http://localhost:8080"
        assert data["readiness_probe"]["timeout"] == 30

    def test_create_tool_type_invalid_definition_type(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that invalid definition types are rejected."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "invalid-tool",
                "display_name": "Invalid Tool",
                "default_port": 8080,
                "definition_type": "invalid",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx",
                "required_variables": [],
            },
        )
        assert response.status_code == 422

    def test_create_tool_type_dockerfile_without_template(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that dockerfile type requires dockerfile_template."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "no-dockerfile",
                "display_name": "No Dockerfile",
                "default_port": 8080,
                "definition_type": "dockerfile",
                "required_variables": [],
            },
        )
        assert response.status_code == 422

    def test_update_tool_type_with_new_fields(
        self, authenticated_client: TestClient
    ) -> None:
        """Test updating a tool type with new fields."""
        # Create tool type first
        create_response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "update-test-tool",
                "display_name": "Update Test Tool",
                "default_port": 8080,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx\n    ports:\n      - '8080:8080'",
                "required_variables": [],
            },
        )
        tool_id = create_response.json()["id"]

        # Update it
        response = authenticated_client.put(
            f"/tool-types/{tool_id}",
            json={
                "display_name": "Updated Name",
                "readiness_probe": {
                    "command": "curl -f http://localhost:8080/health",
                    "timeout": 60,
                    "interval": 5,
                },
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["display_name"] == "Updated Name"
        assert (
            data["readiness_probe"]["command"] == "curl -f http://localhost:8080/health"
        )

    def test_validate_tool_type_compose(self, authenticated_client: TestClient) -> None:
        """Test validating compose template."""
        response = authenticated_client.post(
            "/tool-types/validate",
            json={
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["valid"] is True

    def test_validate_tool_type_invalid_compose(
        self, authenticated_client: TestClient
    ) -> None:
        """Test validating invalid compose template."""
        response = authenticated_client.post(
            "/tool-types/validate",
            json={
                "definition_type": "compose",
                "compose_template": "invalid: yaml: [",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["valid"] is False
        assert "errors" in data

    def test_validate_tool_type_dockerfile(
        self, authenticated_client: TestClient
    ) -> None:
        """Test validating dockerfile template."""
        response = authenticated_client.post(
            "/tool-types/validate",
            json={
                "definition_type": "dockerfile",
                "dockerfile_template": "FROM python:3.11\nRUN pip install flask",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["valid"] is True

    def test_get_tool_type_returns_new_fields(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that GET returns new fields."""
        # Create tool type with all fields
        create_response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "full-tool",
                "display_name": "Full Tool",
                "category": "editor",
                "interface_type": "web",
                "default_port": 8443,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: code-server\n    command: --bind-addr 0.0.0.0:8443\n    ports:\n      - '8443:8443'\n    volumes:\n      - \"{{REPO_PATH}}:/workspace\"",
                "readiness_probe": {
                    "command": "curl -f http://localhost:8443",
                    "timeout": 30,
                    "interval": 2,
                },
                "required_variables": ["REPO_PATH"],
            },
        )
        tool_id = create_response.json()["id"]

        # Get it
        response = authenticated_client.get(f"/tool-types/{tool_id}")
        assert response.status_code == 200
        data = response.json()
        assert data["definition_type"] == "compose"
        assert data["category"] == "editor"
        assert data["interface_type"] == "web"
        assert "readiness_probe" in data

    def test_create_tool_type_without_port_fails(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that creating a tool type requiring a port with default_port=0 fails validation."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "no-port-tool",
                "display_name": "No Port Tool",
                "category": "utility",
                "interface_type": "web",
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx\n    ports:\n      - '8080:8080'",
                "required_variables": [],
            },
        )
        assert response.status_code == 422
        data = response.json()
        assert "default_port" in str(data)

    def test_create_tool_type_with_port_mismatch_fails(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that port mismatch between default_port and compose template fails."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "port-mismatch-tool",
                "display_name": "Port Mismatch Tool",
                "category": "utility",
                "interfaces": ["web"],
                "default_port": 9999,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: nginx\n    ports:\n      - '8080:8080'",
                "required_variables": [],
            },
        )
        assert response.status_code == 422
        _ = response.json()

    def test_create_tool_type_with_startup_command(
        self, authenticated_client: TestClient
    ) -> None:
        """Test creating a tool type with startup_command."""
        response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "startup-tool",
                "display_name": "Startup Tool",
                "category": "utility",
                "interface_type": "terminal",
                "requires_port": False,
                "default_port": 8080,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: alpine\n    command: sleep 3600",
                "startup_command": "cd /workspace && ls",
                "required_variables": [],
            },
        )
        assert response.status_code == 201
        data = response.json()
        assert data["startup_command"] == "cd /workspace && ls"
        assert data["interface_type"] == "terminal"

    def test_update_tool_type_startup_command(
        self, authenticated_client: TestClient
    ) -> None:
        """Test updating a tool type's startup_command."""
        # Create tool type first
        create_response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "update-startup-tool",
                "display_name": "Update Startup Tool",
                "interface_type": "terminal",
                "requires_port": False,
                "default_port": 8080,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: alpine\n    command: sleep 3600",
                "required_variables": [],
            },
        )
        tool_id = create_response.json()["id"]

        # Update with startup_command
        response = authenticated_client.put(
            f"/tool-types/{tool_id}",
            json={
                "startup_command": "source /etc/profile",
                "requires_port": False,
                "default_port": 8080,
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["startup_command"] == "source /etc/profile"

    def test_get_tool_type_returns_startup_command(
        self, authenticated_client: TestClient
    ) -> None:
        """Test that GET returns startup_command."""
        create_response = authenticated_client.post(
            "/tool-types",
            json={
                "name": "get-startup-tool",
                "display_name": "Get Startup Tool",
                "interface_type": "terminal",
                "requires_port": False,
                "default_port": 8080,
                "definition_type": "compose",
                "compose_template": "version: '3.8'\nservices:\n  app:\n    image: alpine\n    command: sleep 3600",
                "startup_command": "echo hello",
                "required_variables": [],
            },
        )
        tool_id = create_response.json()["id"]

        response = authenticated_client.get(f"/tool-types/{tool_id}")
        assert response.status_code == 200
        data = response.json()
        assert data["startup_command"] == "echo hello"
