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 (
    AnalyzeClickPatternsRequest,
    DetectConversionFraudRequest,
    ScorePlacementQualityRequest,
    FilterInvalidTrafficRequest,
    MonitorAccountSecurityRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def analyze_click_patterns_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AnalyzeClickPatternsRequest.model_validate(arguments)
    try:
        from ..fraud_detection import FraudDetectionEngine
        engine = FraudDetectionEngine(client)
        
        data = await engine.analyze_click_patterns(
            ad_account_id=request.ad_account_id,
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            time_range=request.time_range,
            anomaly_threshold=request.anomaly_threshold,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_analyze_click_patterns_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def detect_conversion_fraud_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = DetectConversionFraudRequest.model_validate(arguments)
    try:
        from ..fraud_detection import FraudDetectionEngine
        engine = FraudDetectionEngine(client)
        
        data = await engine.detect_conversion_fraud(
            ad_account_id=request.ad_account_id,
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            time_range=request.time_range,
            conversion_event=request.conversion_event,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_detect_conversion_fraud_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def score_placement_quality_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ScorePlacementQualityRequest.model_validate(arguments)
    try:
        from ..fraud_detection import FraudDetectionEngine
        engine = FraudDetectionEngine(client)
        
        data = await engine.score_placement_quality(
            ad_account_id=request.ad_account_id,
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            time_range=request.time_range,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_score_placement_quality_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def filter_invalid_traffic_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = FilterInvalidTrafficRequest.model_validate(arguments)
    try:
        from ..fraud_detection import FraudDetectionEngine
        engine = FraudDetectionEngine(client)
        
        data = await engine.filter_invalid_traffic(
            ad_account_id=request.ad_account_id,
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            time_range=request.time_range,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_filter_invalid_traffic_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def monitor_account_security_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = MonitorAccountSecurityRequest.model_validate(arguments)
    try:
        from ..fraud_detection import FraudDetectionEngine
        engine = FraudDetectionEngine(client)
        
        data = await engine.monitor_account_security(
            ad_account_id=request.ad_account_id,
            lookback_days=request.lookback_days,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_monitor_account_security_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.fraud.analyze_click_patterns": (
            mcp_types.Tool(
                name="meta.fraud.analyze_click_patterns",
                description="Analyze click patterns to detect bot farm activity, geographic anomalies, suspicious clustering, and click fraud. Use for ad spend protection and invalid traffic detection.",
                inputSchema=_tool_schema(AnalyzeClickPatternsRequest),
            ),
            partial(analyze_click_patterns_handler, client),
        ),
        "meta.fraud.detect_conversion_fraud": (
            mcp_types.Tool(
                name="meta.fraud.detect_conversion_fraud",
                description="Detect fake conversions, fraudulent purchases, and conversion manipulation. Analyzes device fingerprints, conversion timing, and attribution anomalies.",
                inputSchema=_tool_schema(DetectConversionFraudRequest),
            ),
            partial(detect_conversion_fraud_handler, client),
        ),
        "meta.fraud.score_placement_quality": (
            mcp_types.Tool(
                name="meta.fraud.score_placement_quality",
                description="Score ad placement quality and identify fraud-prone placements. Generates exclusion list recommendations for brand safety and ad spend protection.",
                inputSchema=_tool_schema(ScorePlacementQualityRequest),
            ),
            partial(score_placement_quality_handler, client),
        ),
        "meta.fraud.filter_invalid_traffic": (
            mcp_types.Tool(
                name="meta.fraud.filter_invalid_traffic",
                description="Filter invalid traffic (IVT) using MRC-compliant detection. Calculates wasted spend on bots and estimates recovery potential for budget optimization.",
                inputSchema=_tool_schema(FilterInvalidTrafficRequest),
            ),
            partial(filter_invalid_traffic_handler, client),
        ),
        "meta.fraud.monitor_account_security": (
            mcp_types.Tool(
                name="meta.fraud.monitor_account_security",
                description="Monitor ad account security for unauthorized access, permission changes, and security threats. Alerts on suspicious login attempts and API key usage.",
                inputSchema=_tool_schema(MonitorAccountSecurityRequest),
            ),
            partial(monitor_account_security_handler, client),
        ),
    }
