"""Tests for membership tools."""

import json
from unittest.mock import AsyncMock, MagicMock

import pytest

from platform_2step_mcp.tools.memberships import (
    MEMBERSHIP_TOOLS,
    handle_membership_tool,
)


class TestMembershipTools:
    """Tests for membership tool definitions."""

    def test_membership_tools_count(self):
        """Test that all membership tools are defined."""
        assert len(MEMBERSHIP_TOOLS) == 2

    def test_list_memberships_tool_defined(self):
        """Test list_memberships tool is properly defined."""
        tool = next((t for t in MEMBERSHIP_TOOLS if t.name == "list_memberships"), None)
        assert tool is not None
        assert "company_id" in tool.inputSchema["required"]
        assert "client_ids" in tool.inputSchema["required"]
        assert "client_ids" in tool.inputSchema["properties"]
        assert tool.inputSchema["properties"]["client_ids"]["type"] == "array"

    def test_get_membership_tool_defined(self):
        """Test get_membership tool is properly defined."""
        tool = next((t for t in MEMBERSHIP_TOOLS if t.name == "get_membership"), None)
        assert tool is not None
        assert "membership_id" in tool.inputSchema["required"]
        # company_id is no longer required for get_membership (inferred from resource)
        assert "company_id" not in tool.inputSchema["required"]


class TestHandleMembershipTool:
    """Tests for handle_membership_tool."""

    @pytest.fixture
    def mock_client(self):
        """Create a mock Platform2StepClient."""
        client = MagicMock()
        client.list_memberships = AsyncMock()
        client.get_membership = AsyncMock()
        return client

    async def test_list_memberships(self, mock_client):
        """Test list_memberships tool handler."""
        mock_client.list_memberships.return_value = {
            "data": [
                {"id": 1, "name": "Basic Plan"},
                {"id": 2, "name": "Premium Plan"},
            ]
        }

        result = await handle_membership_tool(
            "list_memberships",
            {"company_id": 1238, "client_ids": [10, 20]},
            mock_client,
        )

        assert len(result) == 1
        assert result[0].type == "text"
        data = json.loads(result[0].text)
        assert len(data["data"]) == 2
        mock_client.list_memberships.assert_called_once_with(
            company_id=1238,
            client_ids=[10, 20],
            page=1,
            per_page=25,
        )

    async def test_list_memberships_with_pagination(self, mock_client):
        """Test list_memberships tool handler with pagination."""
        mock_client.list_memberships.return_value = {"data": []}

        await handle_membership_tool(
            "list_memberships",
            {"company_id": 1238, "client_ids": [10], "page": 2, "per_page": 10},
            mock_client,
        )

        mock_client.list_memberships.assert_called_once_with(
            company_id=1238,
            client_ids=[10],
            page=2,
            per_page=10,
        )

    async def test_get_membership(self, mock_client):
        """Test get_membership tool handler."""
        mock_client.get_membership.return_value = {
            "id": 123,
            "name": "Premium Plan",
            "price": 19999,
        }

        result = await handle_membership_tool(
            "get_membership",
            {"membership_id": 123},
            mock_client,
        )

        assert len(result) == 1
        data = json.loads(result[0].text)
        assert data["id"] == 123
        assert data["name"] == "Premium Plan"
        mock_client.get_membership.assert_called_once_with(
            membership_id=123,
            date=None,
        )

    async def test_get_membership_with_date(self, mock_client):
        """Test get_membership tool handler with date parameter."""
        mock_client.get_membership.return_value = {"id": 123, "name": "Premium Plan"}

        await handle_membership_tool(
            "get_membership",
            {"membership_id": 123, "date": "2024-01-15"},
            mock_client,
        )

        mock_client.get_membership.assert_called_once_with(
            membership_id=123,
            date="2024-01-15",
        )

    async def test_unknown_tool_raises_error(self, mock_client):
        """Test that unknown tool raises ValueError."""
        with pytest.raises(ValueError, match="Unknown membership tool"):
            await handle_membership_tool(
                "unknown_tool",
                {},
                mock_client,
            )
