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 (
    CampaignHealthRequest,
    OptimizationSuggestionsRequest,
    CreativeAnalysisRequest,
    AudienceOverlapRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def campaign_health_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = CampaignHealthRequest.model_validate(arguments)
    try:
        from ..helpers import CampaignAnalyzer
        analyzer = CampaignAnalyzer(client)
        
        health = await analyzer.analyze_campaign_health(
            campaign_id=request.campaign_id,
            days_back=request.days_back,
        )
        
        return ToolResult(ok=True, data={
            "campaign_id": health.campaign_id,
            "campaign_name": health.campaign_name,
            "overall_status": health.overall_status.value,
            "score": health.score,
            "metrics": [{
                "name": metric.name,
                "value": metric.value,
                "threshold": metric.threshold,
                "status": metric.status.value,
                "description": metric.description,
                "recommendation": metric.recommendation,
            } for metric in health.metrics],
            "critical_issues": health.critical_issues,
            "recommendations": health.recommendations,
        })
    except Exception as exc:
        logger.error("tool_campaign_health_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def optimization_suggestions_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = OptimizationSuggestionsRequest.model_validate(arguments)
    try:
        from ..helpers import CampaignAnalyzer
        analyzer = CampaignAnalyzer(client)
        
        suggestions = await analyzer.get_optimization_suggestions(
            campaign_id=request.campaign_id,
            days_back=request.days_back,
        )
        
        return ToolResult(ok=True, data=[{
            "type": suggestion.type.value,
            "priority": suggestion.priority,
            "title": suggestion.title,
            "description": suggestion.description,
            "impact": suggestion.impact,
            "effort": suggestion.effort,
            "estimated_improvement": suggestion.estimated_improvement,
            "action_required": suggestion.action_required,
        } for suggestion in suggestions])
    except Exception as exc:
        logger.error("tool_optimization_suggestions_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def creative_analysis_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = CreativeAnalysisRequest.model_validate(arguments)
    try:
        from ..helpers import CampaignAnalyzer
        analyzer = CampaignAnalyzer(client)
        
        performances = await analyzer.analyze_creative_performance(
            campaign_id=request.campaign_id,
            days_back=request.days_back,
        )
        
        return ToolResult(ok=True, data=[{
            "creative_id": perf.creative_id,
            "creative_name": perf.creative_name,
            "impressions": perf.impressions,
            "clicks": perf.clicks,
            "ctr": perf.ctr,
            "cpm": perf.cpm,
            "cpc": perf.cpc,
            "conversions": perf.conversions,
            "cost_per_conversion": perf.cost_per_conversion,
            "performance_score": perf.performance_score,
            "recommendations": perf.recommendations,
        } for perf in performances])
    except Exception as exc:
        logger.error("tool_creative_analysis_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def audience_overlap_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = AudienceOverlapRequest.model_validate(arguments)
    try:
        from ..helpers import CampaignAnalyzer
        analyzer = CampaignAnalyzer(client)
        
        overlaps = await analyzer.detect_audience_overlap(
            ad_account_id=request.ad_account_id,
            audience_ids=request.audience_ids,
        )
        
        return ToolResult(ok=True, data=[{
            "audience_1_id": overlap.audience_1_id,
            "audience_1_name": overlap.audience_1_name,
            "audience_2_id": overlap.audience_2_id,
            "audience_2_name": overlap.audience_2_name,
            "overlap_percentage": overlap.overlap_percentage,
            "overlap_size": overlap.overlap_size,
            "recommendation": overlap.recommendation,
        } for overlap in overlaps])
    except Exception as exc:
        logger.error("tool_audience_overlap_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.campaign_health": (
            mcp_types.Tool(
                name="meta.campaign_health",
                description="Analyze campaign health with score and status. Check delivery, pacing, learning phase, and performance issues. Use for campaign troubleshooting.",
                inputSchema=_tool_schema(CampaignHealthRequest),
            ),
            partial(campaign_health_handler, client),
        ),
        "meta.optimization_suggestions": (
            mcp_types.Tool(
                name="meta.optimization_suggestions",
                description="Get AI-powered optimization suggestions for campaigns. Prioritized recommendations with impact estimates. Use for campaign improvement.",
                inputSchema=_tool_schema(OptimizationSuggestionsRequest),
            ),
            partial(optimization_suggestions_handler, client),
        ),
        "meta.creative_analysis": (
            mcp_types.Tool(
                name="meta.creative_analysis",
                description="Analyze creative performance with CTR, CPC, and conversion metrics. Rank creatives and identify winners. Use for creative optimization.",
                inputSchema=_tool_schema(CreativeAnalysisRequest),
            ),
            partial(creative_analysis_handler, client),
        ),
        "meta.audience_overlap": (
            mcp_types.Tool(
                name="meta.audience_overlap",
                description="Detect audience overlap between ad sets and campaigns. Identify cannibalizing audiences. Use for audience consolidation.",
                inputSchema=_tool_schema(AudienceOverlapRequest),
            ),
            partial(audience_overlap_handler, client),
        ),
    }
