from typing import Any, Dict, Tuple
from functools import partial

from mcp import types as mcp_types

from ..logging import get_logger
from ..meta_client import MetaClient
from ..schemas import (
    AggregateByObjectiveRequest,
    AggregateByStatusRequest,
    AggregateSpendingDistributionRequest,
    AggregatePerformanceSummaryRequest,
    IdentifyTopPerformersRequest,
    IdentifyBottomPerformersRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def aggregate_by_objective_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AggregateByObjectiveRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.aggregate_by_objective(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_aggregate_by_objective_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def aggregate_by_status_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AggregateByStatusRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.aggregate_by_status(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_aggregate_by_status_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def aggregate_spending_distribution_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AggregateSpendingDistributionRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.aggregate_spending_distribution(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_aggregate_spending_distribution_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def aggregate_performance_summary_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AggregatePerformanceSummaryRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.aggregate_performance_summary(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_aggregate_performance_summary_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def identify_top_performers_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = IdentifyTopPerformersRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.identify_top_performers(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_identify_top_performers_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def identify_bottom_performers_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = IdentifyBottomPerformersRequest.model_validate(arguments)
    try:
        from ..aggregation_tools import get_aggregator
        aggregator = get_aggregator()
        
        data = await aggregator.identify_bottom_performers(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_identify_bottom_performers_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

def get_tools(client: MetaClient) -> Dict[str, Tuple[mcp_types.Tool, ToolHandler]]:
    return {
        "meta.aggregate.by_objective": (
            mcp_types.Tool(
                name="meta.aggregate.by_objective",
                description="Aggregate performance data by campaign objective. Compare awareness vs conversion campaigns. Use for objective-level reporting.",
                inputSchema=_tool_schema(AggregateByObjectiveRequest),
            ),
            partial(aggregate_by_objective_handler, client),
        ),
        "meta.aggregate.by_status": (
            mcp_types.Tool(
                name="meta.aggregate.by_status",
                description="Aggregate performance data by campaign status. Compare active, paused, and completed campaigns. Use for status-level reporting.",
                inputSchema=_tool_schema(AggregateByStatusRequest),
            ),
            partial(aggregate_by_status_handler, client),
        ),
        "meta.aggregate.spending_distribution": (
            mcp_types.Tool(
                name="meta.aggregate.spending_distribution",
                description="Analyze spending distribution across campaigns, objectives, and time periods. Visualize budget allocation. Use for spend analysis.",
                inputSchema=_tool_schema(AggregateSpendingDistributionRequest),
            ),
            partial(aggregate_spending_distribution_handler, client),
        ),
        "meta.aggregate.performance_summary": (
            mcp_types.Tool(
                name="meta.aggregate.performance_summary",
                description="Get executive performance summary with KPIs, trends, and highlights. Account-level roll-up. Use for executive reporting.",
                inputSchema=_tool_schema(AggregatePerformanceSummaryRequest),
            ),
            partial(aggregate_performance_summary_handler, client),
        ),
        "meta.aggregate.top_performers": (
            mcp_types.Tool(
                name="meta.aggregate.top_performers",
                description="Identify top-performing campaigns, ad sets, and ads by any metric. Find winners to scale. Use for performance analysis.",
                inputSchema=_tool_schema(IdentifyTopPerformersRequest),
            ),
            partial(identify_top_performers_handler, client),
        ),
        "meta.aggregate.bottom_performers": (
            mcp_types.Tool(
                name="meta.aggregate.bottom_performers",
                description="Identify bottom-performing entities wasting budget. Find losers to pause or optimize. Use for budget recovery.",
                inputSchema=_tool_schema(IdentifyBottomPerformersRequest),
            ),
            partial(identify_bottom_performers_handler, client),
        ),
    }
