"""Tests for tool registry API interactions."""

from __future__ import annotations

from unittest.mock import Mock, patch

import pytest
import requests

from frisk_sdk.core.tool_registry import (
    RegisterToolProperties,
    register_tools,
    aregister_tools,
)


@pytest.mark.asyncio
class TestRegisterToolsAsync:
    @patch("frisk_sdk.core.tool_registry.requests.post")
    async def test_register_tools_posts_expected_payload_and_headers(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = [{"id": "tool_123", "name": "send_email"}]
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={
                    "type": "object",
                    "properties": {"to": {"type": "string"}},
                },
                output_json_schema={
                    "type": "object",
                    "properties": {"id": {"type": "string"}},
                },
                response_format="json",
            )
        ]

        result = await aregister_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        mock_post.assert_called_once()
        call_args = mock_post.call_args
        assert call_args.args[0] == "https://api.frisk.ai/tool-registry/register-tools"

        assert call_args.kwargs["json"] == {
            "properties": [
                {
                    "name": "send_email",
                    "description": "Send an email",
                    "inputJsonSchema": {
                        "type": "object",
                        "properties": {"to": {"type": "string"}},
                    },
                    "outputJsonSchema": {
                        "type": "object",
                        "properties": {"id": {"type": "string"}},
                    },
                    "responseFormat": "json",
                }
            ]
        }
        assert call_args.kwargs["headers"] == {
            "Authorization": "Bearer access_token_123",
            "Content-Type": "application/json",
        }
        assert call_args.kwargs["timeout"] == 10

        assert result == {
            "send_email": {
                "id": "tool_123",
                "name": "send_email",
            }
        }

    @patch("frisk_sdk.core.tool_registry.requests.post")
    async def test_register_tools_empty_properties_returns_early(self, mock_post):
        result = await aregister_tools(
            properties=[],
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        mock_post.assert_not_called()
        assert result == {}

    @patch("frisk_sdk.core.tool_registry.requests.post")
    async def test_register_tools_http_error_returns_empty_dict(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 401
        mock_response.text = "unauthorized"
        mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
            response=mock_response
        )
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={},
                output_json_schema={},
                response_format="json",
            )
        ]

        result = await aregister_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        assert result == {}

    @patch("frisk_sdk.core.tool_registry.requests.post")
    async def test_register_tools_invalid_response_returns_empty_dict(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"id": "tool_123", "name": "send_email"}
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={},
                output_json_schema={},
                response_format="json",
            )
        ]

        result = await aregister_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        assert result == {}


class TestRegisterToolsSync:
    @patch("frisk_sdk.core.tool_registry.requests.post")
    def test_register_tools_posts_expected_payload_and_headers(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = [{"id": "tool_123", "name": "send_email"}]
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={
                    "type": "object",
                    "properties": {"to": {"type": "string"}},
                },
                output_json_schema={
                    "type": "object",
                    "properties": {"id": {"type": "string"}},
                },
                response_format="json",
            )
        ]

        result = register_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        mock_post.assert_called_once()
        call_args = mock_post.call_args
        assert call_args.args[0] == "https://api.frisk.ai/tool-registry/register-tools"

        assert call_args.kwargs["json"] == {
            "properties": [
                {
                    "name": "send_email",
                    "description": "Send an email",
                    "inputJsonSchema": {
                        "type": "object",
                        "properties": {"to": {"type": "string"}},
                    },
                    "outputJsonSchema": {
                        "type": "object",
                        "properties": {"id": {"type": "string"}},
                    },
                    "responseFormat": "json",
                }
            ]
        }
        assert call_args.kwargs["headers"] == {
            "Authorization": "Bearer access_token_123",
            "Content-Type": "application/json",
        }
        assert call_args.kwargs["timeout"] == 10

        assert result == {
            "send_email": {
                "id": "tool_123",
                "name": "send_email",
            }
        }

    @patch("frisk_sdk.core.tool_registry.requests.post")
    def test_register_tools_empty_properties_returns_early(self, mock_post):
        result = register_tools(
            properties=[],
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        mock_post.assert_not_called()
        assert result == {}

    @patch("frisk_sdk.core.tool_registry.requests.post")
    def test_register_tools_http_error_returns_empty_dict(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 401
        mock_response.text = "unauthorized"
        mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
            response=mock_response
        )
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={},
                output_json_schema={},
                response_format="json",
            )
        ]

        result = register_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        assert result == {}

    @patch("frisk_sdk.core.tool_registry.requests.post")
    def test_register_tools_invalid_response_returns_empty_dict(self, mock_post):
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"id": "tool_123", "name": "send_email"}
        mock_post.return_value = mock_response

        props = [
            RegisterToolProperties(
                name="send_email",
                description="Send an email",
                input_json_schema={},
                output_json_schema={},
                response_format="json",
            )
        ]

        result = register_tools(
            properties=props,
            api_base_url="https://api.frisk.ai",
            access_token="access_token_123",
        )

        assert result == {}
