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 (
    ValidateBudgetChangeRequest,
    ValidateTargetingRequest,
    ValidateCreativeRequest,
    ValidateCampaignStructureRequest,
    PreviewBudgetImpactRequest,
    PreviewBidImpactRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def validate_budget_change_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ValidateBudgetChangeRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.validate_budget_change(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_validate_budget_change_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def validate_targeting_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ValidateTargetingRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.validate_targeting(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_validate_targeting_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def validate_creative_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ValidateCreativeRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.validate_creative(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_validate_creative_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def validate_campaign_structure_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ValidateCampaignStructureRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.validate_campaign_structure(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_validate_campaign_structure_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def preview_budget_impact_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = PreviewBudgetImpactRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.preview_budget_impact(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_preview_budget_impact_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def preview_bid_impact_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = PreviewBidImpactRequest.model_validate(arguments)
    try:
        from ..validation_tools import get_validation_engine
        engine = get_validation_engine()
        
        data = await engine.preview_bid_impact(request)
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_preview_bid_impact_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.validate_budget_change": (
            mcp_types.Tool(
                name="meta.validate_budget_change",
                description="Validate budget changes before applying. Check for learning phase disruption and pacing issues. Use for safe budget modifications.",
                inputSchema=_tool_schema(ValidateBudgetChangeRequest),
            ),
            partial(validate_budget_change_handler, client),
        ),
        "meta.validate_targeting": (
            mcp_types.Tool(
                name="meta.validate_targeting",
                description="Validate targeting settings for audience size, overlap, and policy compliance. Pre-flight check before launch. Use for targeting QA.",
                inputSchema=_tool_schema(ValidateTargetingRequest),
            ),
            partial(validate_targeting_handler, client),
        ),
        "meta.validate_creative": (
            mcp_types.Tool(
                name="meta.validate_creative",
                description="Validate creative assets for specs, policy, and quality. Check image dimensions, video length, and text ratios. Use for creative QA.",
                inputSchema=_tool_schema(ValidateCreativeRequest),
            ),
            partial(validate_creative_handler, client),
        ),
        "meta.validate_campaign_structure": (
            mcp_types.Tool(
                name="meta.validate_campaign_structure",
                description="Validate campaign structure for best practices. Check ad set count, naming, and organization. Use for account structure review.",
                inputSchema=_tool_schema(ValidateCampaignStructureRequest),
            ),
            partial(validate_campaign_structure_handler, client),
        ),
        "meta.preview_budget_impact": (
            mcp_types.Tool(
                name="meta.preview_budget_impact",
                description="Preview impact of budget changes on reach, conversions, and CPA. Simulate before applying changes. Use for budget planning.",
                inputSchema=_tool_schema(PreviewBudgetImpactRequest),
            ),
            partial(preview_budget_impact_handler, client),
        ),
        "meta.preview_bid_impact": (
            mcp_types.Tool(
                name="meta.preview_bid_impact",
                description="Preview impact of bid changes on volume, cost, and win rates. Simulate auction outcomes. Use for bid strategy planning.",
                inputSchema=_tool_schema(PreviewBidImpactRequest),
            ),
            partial(preview_bid_impact_handler, client),
        ),
    }
