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 (
    CreateScheduleRequest,
    ListSchedulesRequest,
    CancelScheduleRequest,
    GetDaypartingRequest,
    SetDaypartingRequest,
    ToolResult
)
from .base import ToolHandler, _tool_schema

logger = get_logger(__name__)

async def create_schedule_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = CreateScheduleRequest.model_validate(arguments)
    try:
        from ..scheduling_tools import ScheduleManager
        manager = ScheduleManager(client)
        
        data = await manager.create_schedule(
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            action_type=request.action_type,
            action_params=request.action_params,
            schedule_date=request.schedule_date,
            schedule_time=request.schedule_time,
            timezone=request.timezone,
            recurring=request.recurring,
            recurring_frequency=request.recurring_frequency,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_create_schedule_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def list_schedules_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = ListSchedulesRequest.model_validate(arguments)
    try:
        from ..scheduling_tools import ScheduleManager
        manager = ScheduleManager(client)
        
        data = await manager.list_schedules(
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            status=request.status,
            limit=request.limit,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_list_schedules_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def cancel_schedule_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = CancelScheduleRequest.model_validate(arguments)
    try:
        from ..scheduling_tools import ScheduleManager
        manager = ScheduleManager(client)
        
        data = await manager.cancel_schedule(
            schedule_id=request.schedule_id,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_cancel_schedule_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def get_dayparting_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = GetDaypartingRequest.model_validate(arguments)
    try:
        from ..scheduling_tools import ScheduleManager
        manager = ScheduleManager(client)
        
        data = await manager.get_dayparting(
            entity_id=request.entity_id,
            entity_type=request.entity_type,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_get_dayparting_failed", error=str(exc))
        return ToolResult(ok=False, error={"message": str(exc)})

async def set_dayparting_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    request = SetDaypartingRequest.model_validate(arguments)
    try:
        from ..scheduling_tools import ScheduleManager
        manager = ScheduleManager(client)
        
        data = await manager.set_dayparting(
            entity_id=request.entity_id,
            entity_type=request.entity_type,
            dayparting_schedule=request.dayparting_schedule,
            timezone=request.timezone,
            bid_adjustments=request.bid_adjustments,
        )
        
        return ToolResult(ok=True, data=data)
    except Exception as exc:
        logger.error("tool_set_dayparting_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.create_schedule": (
            mcp_types.Tool(
                name="meta.create_schedule",
                description="Schedule an action for future execution. Automate budget changes, status updates, and more. Use for scheduled automation.",
                inputSchema=_tool_schema(CreateScheduleRequest),
            ),
            partial(create_schedule_handler, client),
        ),
        "meta.list_schedules": (
            mcp_types.Tool(
                name="meta.list_schedules",
                description="List all scheduled actions with status and timing. View pending and completed schedules. Use for schedule management.",
                inputSchema=_tool_schema(ListSchedulesRequest),
            ),
            partial(list_schedules_handler, client),
        ),
        "meta.cancel_schedule": (
            mcp_types.Tool(
                name="meta.cancel_schedule",
                description="Cancel a scheduled action before execution. Stop pending automations. Use for schedule cancellation.",
                inputSchema=_tool_schema(CancelScheduleRequest),
            ),
            partial(cancel_schedule_handler, client),
        ),
        "meta.get_dayparting": (
            mcp_types.Tool(
                name="meta.get_dayparting",
                description="Get dayparting schedule showing active hours by day of week. View time-based ad delivery. Use for dayparting analysis.",
                inputSchema=_tool_schema(GetDaypartingRequest),
            ),
            partial(get_dayparting_handler, client),
        ),
        "meta.set_dayparting": (
            mcp_types.Tool(
                name="meta.set_dayparting",
                description="Set dayparting schedule with bid adjustments by hour. Optimize for peak performance times. Use for time-based optimization.",
                inputSchema=_tool_schema(SetDaypartingRequest),
            ),
            partial(set_dayparting_handler, client),
        ),
    }
