"""Tests for the fixture/test file generator."""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from mcp_forge._types import ToolInfo
from mcp_forge.fixtures import generate_test_file, record_fixtures


def _make_tools() -> list[ToolInfo]:
    return [
        ToolInfo(
            name="echo",
            description="Echo input back",
            input_schema={
                "type": "object",
                "required": ["message"],
                "properties": {"message": {"type": "string"}},
            },
        ),
        ToolInfo(
            name="add",
            description="Add two numbers",
            input_schema={
                "type": "object",
                "required": ["a", "b"],
                "properties": {
                    "a": {"type": "number"},
                    "b": {"type": "number"},
                },
            },
        ),
    ]


class TestGenerateTestFile:
    def test_creates_file(self, tmp_path):
        output = tmp_path / "test_gen.py"
        tools = _make_tools()
        result = generate_test_file(tools, "python server.py", output)
        assert result.exists()
        assert result.suffix == ".py"

    def test_contains_imports(self, tmp_path):
        output = tmp_path / "test_gen.py"
        generate_test_file(_make_tools(), "python server.py", output)
        content = output.read_text()
        assert "from mcp_forge" in content
        assert "MCPTestClient" in content
        assert "pytest" in content

    def test_contains_fixture(self, tmp_path):
        output = tmp_path / "test_gen.py"
        generate_test_file(_make_tools(), "python server.py", output)
        content = output.read_text()
        assert "async def client" in content or "@pytest.fixture" in content

    def test_contains_tool_tests(self, tmp_path):
        output = tmp_path / "test_gen.py"
        generate_test_file(_make_tools(), "python server.py", output)
        content = output.read_text()
        assert "test_echo" in content
        assert "test_add" in content

    def test_contains_snapshot_tests(self, tmp_path):
        output = tmp_path / "test_gen.py"
        generate_test_file(_make_tools(), "python server.py", output)
        content = output.read_text()
        assert "forge_snapshot" in content

    def test_is_valid_python(self, tmp_path):
        output = tmp_path / "test_gen.py"
        generate_test_file(_make_tools(), "python server.py", output)
        content = output.read_text()
        # Should parse without syntax errors
        compile(content, str(output), "exec")


class TestRecordFixtures:
    def test_creates_fixture_dirs(self, tmp_path):
        tools = _make_tools()
        results = {
            "echo": {"is_error": False, "content": [{"type": "text", "text": "hello"}]},
        }
        created = record_fixtures(tools, results, tmp_path / "fixtures")
        assert len(created) > 0
        assert (tmp_path / "fixtures" / "echo").is_dir()
        assert (tmp_path / "fixtures" / "add").is_dir()

    def test_saves_schemas(self, tmp_path):
        tools = _make_tools()
        record_fixtures(tools, {}, tmp_path / "fixtures")
        schema_file = tmp_path / "fixtures" / "echo" / "schema.json"
        assert schema_file.exists()
        data = json.loads(schema_file.read_text())
        assert data["name"] == "echo"

    def test_saves_sample_inputs(self, tmp_path):
        tools = _make_tools()
        record_fixtures(tools, {}, tmp_path / "fixtures")
        input_file = tmp_path / "fixtures" / "echo" / "sample_input.json"
        assert input_file.exists()
        data = json.loads(input_file.read_text())
        assert "message" in data

    def test_saves_results(self, tmp_path):
        tools = _make_tools()
        results = {
            "echo": {"is_error": False, "content": [{"type": "text", "text": "hello"}]},
        }
        record_fixtures(tools, results, tmp_path / "fixtures")
        output_file = tmp_path / "fixtures" / "echo" / "sample_output.json"
        assert output_file.exists()
        data = json.loads(output_file.read_text())
        assert data["content"][0]["text"] == "hello"
