"""Unit tests for MCP tools — verifies correct endpoint URLs and params."""

from __future__ import annotations

from unittest.mock import MagicMock

import pytest

from g8_mcp_server.auth import set_api_key
from g8_mcp_server.client import G8Client, G8ClientError, _handle_response
from g8_mcp_server.server import create_remote_app, create_server


@pytest.fixture
def mock_env(monkeypatch):
    monkeypatch.setenv("G8_API_KEY", "test_key_123")
    monkeypatch.setenv("G8_API_URL", "https://test.graph8.com")


@pytest.fixture
def client(mock_env):
    return G8Client()


def _tool_names(server):
    return list(server._tool_manager._tools.keys())


class TestG8Client:
    def test_missing_api_key_required(self, monkeypatch):
        monkeypatch.delenv("G8_API_KEY", raising=False)
        with pytest.raises(G8ClientError, match="G8_API_KEY"):
            G8Client(require_key=True)

    def test_missing_api_key_not_required(self, monkeypatch):
        monkeypatch.delenv("G8_API_KEY", raising=False)
        client = G8Client(require_key=False)
        assert client._env_api_key == ""

    def test_contextvars_key_takes_priority(self, client):
        set_api_key("context_key_456")
        assert client._headers["Authorization"] == "Bearer context_key_456"
        # Clean up
        from g8_mcp_server.auth import _api_key
        _api_key.set("")

    def test_env_key_fallback(self, client):
        assert client._headers["Authorization"] == "Bearer test_key_123"
        assert client._headers["Content-Type"] == "application/json"

    def test_base_url(self, client):
        assert client.base_url == "https://test.graph8.com"


class TestRepoTools:
    def test_tools_registered(self, client):
        from mcp.server import FastMCP
        from g8_mcp_server.tools import repos
        server = FastMCP("test")
        repos.register(server, client)
        names = _tool_names(server)
        assert "g8_connect_repo" in names
        assert "g8_scan_repo" in names
        assert "g8_get_scan_results" in names
        assert "g8_status" in names
        assert "g8_doctor" in names


class TestInstallTools:
    def test_tools_registered(self, client):
        from mcp.server import FastMCP
        from g8_mcp_server.tools import install
        server = FastMCP("test")
        install.register(server, client)
        names = _tool_names(server)
        assert "g8_install_spine" in names
        assert "g8_apply_install" in names


class TestCampaignTools:
    def test_tools_registered(self, client):
        from mcp.server import FastMCP
        from g8_mcp_server.tools import campaigns
        server = FastMCP("test")
        campaigns.register(server, client)
        names = _tool_names(server)
        assert "g8_list_campaigns" in names
        assert "g8_get_campaign" in names
        assert "g8_launch_campaign" in names


class TestPlatformTools:
    def test_tools_registered(self, client):
        from mcp.server import FastMCP
        from g8_mcp_server.tools import platform
        server = FastMCP("test")
        platform.register(server, client)
        names = _tool_names(server)
        assert "g8_search_contacts" in names
        assert "g8_search_companies" in names
        assert "g8_lookup_person" in names
        assert "g8_lookup_company" in names
        assert "g8_add_to_sequence" in names


class TestServerBootstrap:
    def test_all_16_tools_registered(self, mock_env):
        server = create_server()
        expected_tools = [
            "g8_connect_repo", "g8_scan_repo", "g8_get_scan_results", "g8_status", "g8_doctor",
            "g8_install_spine", "g8_apply_install",
            "g8_list_campaigns", "g8_get_campaign", "g8_launch_campaign",
            "g8_search_kb",
            "g8_search_contacts", "g8_search_companies", "g8_lookup_person", "g8_lookup_company", "g8_add_to_sequence",
        ]
        names = _tool_names(server)
        for tool_name in expected_tools:
            assert tool_name in names, f"Missing tool: {tool_name}"
        assert len(expected_tools) == 16


class TestRemoteApp:
    def test_creates_without_env_key(self, monkeypatch):
        monkeypatch.delenv("G8_API_KEY", raising=False)
        app = create_remote_app()
        assert app is not None

    def test_creates_with_env_key(self, mock_env):
        app = create_remote_app()
        assert app is not None


class TestClientErrorHandling:
    def test_401_error(self):
        resp = MagicMock()
        resp.status_code = 401
        with pytest.raises(G8ClientError, match="Invalid API key"):
            _handle_response(resp)

    def test_429_error(self):
        resp = MagicMock()
        resp.status_code = 429
        with pytest.raises(G8ClientError, match="Rate limit"):
            _handle_response(resp)

    def test_404_error(self):
        resp = MagicMock()
        resp.status_code = 404
        with pytest.raises(G8ClientError, match="not found"):
            _handle_response(resp)

    def test_generic_error(self):
        resp = MagicMock()
        resp.status_code = 500
        resp.json.return_value = {"message": "Internal server error"}
        resp.text = "Internal server error"
        with pytest.raises(G8ClientError, match="Internal server error"):
            _handle_response(resp)

    def test_success_json(self):
        resp = MagicMock()
        resp.status_code = 200
        resp.json.return_value = {"data": {"id": "test"}}
        result = _handle_response(resp)
        assert result == {"data": {"id": "test"}}
