"""
Test category-related MCP tools.
"""

from unittest.mock import MagicMock

import ynab
from assertions import assert_pagination_info, extract_response_data
from conftest import create_ynab_category
from fastmcp.client import Client, FastMCPTransport


async def test_list_categories_success(
    mock_repository: MagicMock, mcp_client: Client[FastMCPTransport]
) -> None:
    """Test successful category listing."""
    visible_category = create_ynab_category(
        id="cat-1",
        name="Groceries",
        note="Food shopping",
        goal_type="TB",
        goal_target=100_000,
        goal_percentage_complete=50,
    )

    hidden_category = create_ynab_category(
        id="cat-hidden",
        name="Hidden Category",
        hidden=True,  # Should be excluded
        budgeted=10_000,
        activity=0,
        balance=10_000,
    )

    category_group = ynab.CategoryGroupWithCategories(
        id="group-1",
        name="Monthly Bills",
        hidden=False,
        deleted=False,
        categories=[visible_category, hidden_category],
    )

    # Mock repository to return category groups
    mock_repository.get_category_groups.return_value = [category_group]

    result = await mcp_client.call_tool("list_categories", {})
    response_data = extract_response_data(result)

    # Should only include visible category
    categories = response_data["categories"]
    assert len(categories) == 1
    assert categories[0]["id"] == "cat-1"
    assert categories[0]["name"] == "Groceries"
    assert categories[0]["category_group_name"] == "Monthly Bills"

    assert_pagination_info(
        response_data["pagination"],
        total_count=1,
        limit=50,
        has_more=False,
    )


async def test_list_category_groups_success(
    mock_repository: MagicMock, mcp_client: Client[FastMCPTransport]
) -> None:
    """Test successful category group listing."""

    category = ynab.Category(
        id="cat-1",
        category_group_id="group-1",
        category_group_name="Monthly Bills",
        name="Test Category",
        hidden=False,
        original_category_group_id=None,
        note=None,
        budgeted=50000,
        activity=-30000,
        balance=20000,
        goal_type=None,
        goal_needs_whole_amount=None,
        goal_day=None,
        goal_cadence=None,
        goal_cadence_frequency=None,
        goal_creation_month=None,
        goal_target=None,
        goal_target_month=None,
        goal_percentage_complete=None,
        goal_months_to_budget=None,
        goal_under_funded=None,
        goal_overall_funded=None,
        goal_overall_left=None,
        deleted=False,
    )

    category_group = ynab.CategoryGroupWithCategories(
        id="group-1",
        name="Monthly Bills",
        hidden=False,
        deleted=False,
        categories=[category],
    )

    # Mock repository to return category groups
    mock_repository.get_category_groups.return_value = [category_group]

    result = await mcp_client.call_tool("list_category_groups", {})

    groups_data = extract_response_data(result)
    # Should return a list of category groups
    assert isinstance(groups_data, list)
    assert len(groups_data) == 1
    group = groups_data[0]
    assert group["id"] == "group-1"
    assert group["name"] == "Monthly Bills"


async def test_list_categories_filters_deleted_and_hidden(
    mock_repository: MagicMock, mcp_client: Client[FastMCPTransport]
) -> None:
    """Test that list_categories automatically filters out deleted and hidden."""

    # Active category (should be included)
    mock_active_category = ynab.Category(
        id="cat-active",
        name="Active Category",
        category_group_id="group-1",
        hidden=False,
        deleted=False,
        note="Active",
        budgeted=10000,
        activity=-5000,
        balance=5000,
        goal_type=None,
        goal_target=None,
        goal_percentage_complete=None,
        goal_under_funded=None,
        goal_creation_month=None,
        goal_target_month=None,
        goal_overall_funded=None,
        goal_overall_left=None,
    )

    # Hidden category (should be excluded)
    mock_hidden_category = ynab.Category(
        id="cat-hidden",
        name="Hidden Category",
        category_group_id="group-1",
        hidden=True,
        deleted=False,
        note="Hidden",
        budgeted=0,
        activity=0,
        balance=0,
        goal_type=None,
        goal_target=None,
        goal_percentage_complete=None,
        goal_under_funded=None,
        goal_creation_month=None,
        goal_target_month=None,
        goal_overall_funded=None,
        goal_overall_left=None,
    )

    # Deleted category (should be excluded)
    mock_deleted_category = ynab.Category(
        id="cat-deleted",
        name="Deleted Category",
        category_group_id="group-1",
        hidden=False,
        deleted=True,
        note="Deleted",
        budgeted=0,
        activity=0,
        balance=0,
        goal_type=None,
        goal_target=None,
        goal_percentage_complete=None,
        goal_under_funded=None,
        goal_creation_month=None,
        goal_target_month=None,
        goal_overall_funded=None,
        goal_overall_left=None,
    )

    category_group = ynab.CategoryGroupWithCategories(
        id="group-1",
        name="Monthly Bills",
        hidden=False,
        deleted=False,
        categories=[
            mock_active_category,
            mock_hidden_category,
            mock_deleted_category,
        ],
    )

    # Mock repository to return category groups
    mock_repository.get_category_groups.return_value = [category_group]

    result = await mcp_client.call_tool("list_categories", {})

    response_data = extract_response_data(result)
    # Should only include the active category
    assert len(response_data["categories"]) == 1
    assert response_data["categories"][0]["id"] == "cat-active"
    assert response_data["categories"][0]["name"] == "Active Category"


async def test_list_category_groups_filters_deleted(
    mock_repository: MagicMock, mcp_client: Client[FastMCPTransport]
) -> None:
    """Test that list_category_groups automatically filters out deleted groups."""

    # Active group (should be included)
    active_group = ynab.CategoryGroupWithCategories(
        id="group-active",
        name="Active Group",
        hidden=False,
        deleted=False,
        categories=[],
    )

    # Deleted group (should be excluded)
    deleted_group = ynab.CategoryGroupWithCategories(
        id="group-deleted",
        name="Deleted Group",
        hidden=False,
        deleted=True,
        categories=[],
    )

    # Mock repository to return category groups
    mock_repository.get_category_groups.return_value = [active_group, deleted_group]

    result = await mcp_client.call_tool("list_category_groups", {})

    response_data = extract_response_data(result)
    # Should only include the active group
    assert isinstance(response_data, list)
    assert len(response_data) == 1
    group = response_data[0]
    assert group["id"] == "group-active"
    assert group["name"] == "Active Group"
