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 (
    PauseUnderperformersRequest,
    ScaleWinnersRequest,
    RotateCreativesRequest,
    RebalanceBudgetsRequest,
    DuplicateWinnerRequest,
    EmergencyStopRequest,
    SmartOptimizationRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def pause_underperformers_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = PauseUnderperformersRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.pause_underperformers(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_pause_underperformers_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def scale_winners_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ScaleWinnersRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.scale_winners(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_scale_winners_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def rotate_creatives_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = RotateCreativesRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.rotate_creatives(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_rotate_creatives_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def rebalance_budgets_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = RebalanceBudgetsRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.rebalance_budgets(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_rebalance_budgets_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def duplicate_winner_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = DuplicateWinnerRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.duplicate_winner(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_duplicate_winner_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def emergency_stop_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = EmergencyStopRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.emergency_stop(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_emergency_stop_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def smart_optimization_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = SmartOptimizationRequest.model_validate(arguments)
    try:
        from ..quick_actions import get_quick_action_engine
        engine = get_quick_action_engine()
        
        data = await engine.smart_optimization(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_smart_optimization_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.pause_underperformers": (
            mcp_types.Tool(
                name="meta.pause_underperformers",
                description="Automatically pause underperforming ads and ad sets based on ROAS, CPA, or CTR thresholds. Stops wasted spend on poor performers. Use for automated optimization.",
                inputSchema=_tool_schema(PauseUnderperformersRequest),
            ),
            partial(pause_underperformers_handler, client),
        ),
        "meta.scale_winners": (
            mcp_types.Tool(
                name="meta.scale_winners",
                description="Automatically scale winning ads by increasing budget. Identifies top performers and applies budget multipliers. Use for scaling proven performers safely.",
                inputSchema=_tool_schema(ScaleWinnersRequest),
            ),
            partial(scale_winners_handler, client),
        ),
        "meta.rotate_creatives": (
            mcp_types.Tool(
                name="meta.rotate_creatives",
                description="Rotate creatives to prevent ad fatigue. Automatically swaps in fresh ads when frequency gets too high. Use for creative refresh automation.",
                inputSchema=_tool_schema(RotateCreativesRequest),
            ),
            partial(rotate_creatives_handler, client),
        ),
        "meta.rebalance_budgets": (
            mcp_types.Tool(
                name="meta.rebalance_budgets",
                description="Rebalance budgets across campaigns based on performance. Shifts spend from underperformers to top performers. Use for portfolio budget optimization.",
                inputSchema=_tool_schema(RebalanceBudgetsRequest),
            ),
            partial(rebalance_budgets_handler, client),
        ),
        "meta.duplicate_winner": (
            mcp_types.Tool(
                name="meta.duplicate_winner",
                description="Duplicate winning ad sets to new audiences or regions. Clone top performers with new targeting. Use for horizontal scaling and market expansion.",
                inputSchema=_tool_schema(DuplicateWinnerRequest),
            ),
            partial(duplicate_winner_handler, client),
        ),
        "meta.emergency_stop": (
            mcp_types.Tool(
                name="meta.emergency_stop",
                description="Emergency stop to immediately pause all active campaigns. Instant kill switch for runaway spend or crisis situations. Use for emergency cost control.",
                inputSchema=_tool_schema(EmergencyStopRequest),
            ),
            partial(emergency_stop_handler, client),
        ),
        "meta.smart_optimization": (
            mcp_types.Tool(
                name="meta.smart_optimization",
                description="Apply AI-powered smart optimization rules across campaigns. Combines pause, scale, rotate, and rebalance actions. Use for hands-off automated management.",
                inputSchema=_tool_schema(SmartOptimizationRequest),
            ),
            partial(smart_optimization_handler, client),
        ),
    }
