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 ToolResult
from .base import ToolHandler

logger = get_logger(__name__)

async def roas_driver_analysis_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine
        # Engine methods usually take Request object or dict. 
        # Inspecting roas_optimization.py (outline):
        # roas_driver_analysis(self, request: ROASDriverAnalysisRequest)
        # We need to construct the request object if engine enforces strict typing or use it as dict if pydantic allows.
        # However, to be safe and simple in wrapper, we can try to pass dict if the engine accepts it (pydantic usually does via parse_obj or if using **args).
        # But this engine seems to define explicit Request classes in roas_optimization.py or schemas.py.
        # Let's assume the pattern of other tools: we might need to update engine or wrapper.
        # But for now, we will try to instantiate the request object if we can import it, OR pass dict if engine supports it.
        # Given I can't easily see if ROASDriverAnalysisRequest is exported from ..roas_optimization, 
        # I'll rely on the engine potentially handling dicts or I'll just pass the dict.
        # NOTE: If this fails in verification, I'll need to fix it.
        engine = ROASOptimizationEngine(client)
        # Mocking exact request object construction might be needed if engine doesn't auto-convert.
        # But for this widespread refactor, I'll assume standard dict execution or that I can fix it later.
        # Wait, the tool definition in MCP uses json schema (dict). 
        # Ideally the engine should take a dict. 
        # If the engine method signature is `request: ROASDriverAnalysisRequest`, I must construct it.
        # Let's try to import it inside the handler to be safe.
        from ..roas_optimization import ROASDriverAnalysisRequest
        req = ROASDriverAnalysisRequest(**arguments)
        return await engine.roas_driver_analysis(req)
    except Exception as exc:
        logger.error("tool_roas_driver_analysis_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def conversion_rate_optimizer_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, ConversionRateOptimizerRequest
        engine = ROASOptimizationEngine(client)
        req = ConversionRateOptimizerRequest(**arguments)
        return await engine.conversion_rate_optimizer(req)
    except Exception as exc:
        logger.error("tool_conversion_rate_optimizer_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def cost_per_acquisition_analyzer_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, CostPerAcquisitionAnalyzerRequest
        engine = ROASOptimizationEngine(client)
        req = CostPerAcquisitionAnalyzerRequest(**arguments)
        return await engine.cost_per_acquisition_analyzer(req)
    except Exception as exc:
        logger.error("tool_cost_per_acquisition_analyzer_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def marginal_roas_calculator_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, MarginalROASCalculatorRequest
        engine = ROASOptimizationEngine(client)
        req = MarginalROASCalculatorRequest(**arguments)
        return await engine.marginal_roas_calculator(req)
    except Exception as exc:
        logger.error("tool_marginal_roas_calculator_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def wasted_spend_identifier_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, WastedSpendIdentifierRequest
        engine = ROASOptimizationEngine(client)
        req = WastedSpendIdentifierRequest(**arguments)
        return await engine.wasted_spend_identifier(req)
    except Exception as exc:
        logger.error("tool_wasted_spend_identifier_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def value_optimization_analyzer_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, ValueOptimizationAnalyzerRequest
        engine = ROASOptimizationEngine(client)
        req = ValueOptimizationAnalyzerRequest(**arguments)
        return await engine.value_optimization_analyzer(req)
    except Exception as exc:
        logger.error("tool_value_optimization_analyzer_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def frequency_cap_optimizer_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, FrequencyCapOptimizerRequest
        engine = ROASOptimizationEngine(client)
        req = FrequencyCapOptimizerRequest(**arguments)
        return await engine.frequency_cap_optimizer(req)
    except Exception as exc:
        logger.error("tool_frequency_cap_optimizer_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def attribution_window_analyzer_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    try:
        from ..roas_optimization import ROASOptimizationEngine, AttributionWindowAnalyzerRequest
        engine = ROASOptimizationEngine(client)
        req = AttributionWindowAnalyzerRequest(**arguments)
        return await engine.attribution_window_analyzer(req)
    except Exception as exc:
        logger.error("tool_attribution_window_analyzer_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.roas.analyze_drivers": (
            mcp_types.Tool(
                name="meta.roas.analyze_drivers",
                description="Analyze ROAS drivers and profitability factors. Identify what impacts return on ad spend (audience, placement, creative, time). Use for ROAS optimization strategy.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(roas_driver_analysis_handler, client),
        ),
        "meta.roas.optimize_conversion_rate": (
            mcp_types.Tool(
                name="meta.roas.optimize_conversion_rate",
                description="Optimize conversion rates across campaigns. Identify high and low converting segments with improvement recommendations. Use for CRO and sales funnel optimization.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(conversion_rate_optimizer_handler, client),
        ),
        "meta.roas.analyze_cpa": (
            mcp_types.Tool(
                name="meta.roas.analyze_cpa",
                description="Analyze cost per acquisition (CPA) trends and drivers. Compare CPA across campaigns, audiences, and time periods. Use for cost efficiency improvements.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(cost_per_acquisition_analyzer_handler, client),
        ),
        "meta.roas.calculate_marginal": (
            mcp_types.Tool(
                name="meta.roas.calculate_marginal",
                description="Calculate marginal ROAS to find optimal spend levels. Identify diminishing returns and budget sweet spots. Use for budget allocation decisions.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(marginal_roas_calculator_handler, client),
        ),
        "meta.roas.identify_wasted_spend": (
            mcp_types.Tool(
                name="meta.roas.identify_wasted_spend",
                description="Identify wasted ad spend on low performers. Find campaigns, audiences, and placements with inefficient spending. Use for budget savings and reallocation.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(wasted_spend_identifier_handler, client),
        ),
        "meta.roas.analyze_value": (
            mcp_types.Tool(
                name="meta.roas.analyze_value",
                description="Analyze value optimization for high-value conversions. Compare purchase value distribution and optimize for revenue. Use for value-based bidding strategy.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(value_optimization_analyzer_handler, client),
        ),
        "meta.roas.optimize_frequency": (
            mcp_types.Tool(
                name="meta.roas.optimize_frequency",
                description="Optimize frequency caps to maximize ROAS. Analyze frequency vs. conversion rate curves and recommend optimal caps. Use for reach and efficiency balance.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(frequency_cap_optimizer_handler, client),
        ),
        "meta.roas.analyze_attribution": (
            mcp_types.Tool(
                name="meta.roas.analyze_attribution",
                description="Analyze attribution windows and conversion measurement. Compare 1-day, 7-day, 28-day click attribution impact on ROAS. Use for measurement accuracy.",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "ad_account_id": {"type": "string"},
                    },
                    "required": ["ad_account_id"],
                },
            ),
            partial(attribution_window_analyzer_handler, client),
        ),
    }
