from __future__ import annotations

from pathlib import Path
from typing import Any

from aiogram.types import FSInputFile

from ..schemas import ToolDefinition, ToolExecutionContext
from .base import object_schema


async def _resolve_media(value: str | None):
    if not value:
        return None
    path = Path(value).expanduser()
    if path.exists() and path.is_file():
        return FSInputFile(str(path))
    return value


def _get_bot(context: ToolExecutionContext):
    bot = context.transport_state.get("bot") if context.transport_state else None
    if bot is None:
        bot = getattr(context.runtime, "telegram_bot", None)
    if bot is None:
        raise RuntimeError("Telegram bot is not available in this execution context")
    return bot


def _chat_id(context: ToolExecutionContext, arguments: dict[str, Any]):
    return arguments.get("chat_id") or context.chat_id


async def telegram_send_message_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    sent = await bot.send_message(
        chat_id=_chat_id(context, arguments),
        text=arguments["text"],
        disable_notification=bool(arguments.get("disable_notification", False)),
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_send_photo_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    photo = await _resolve_media(arguments.get("photo"))
    sent = await bot.send_photo(
        chat_id=_chat_id(context, arguments),
        photo=photo,
        caption=arguments.get("caption"),
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_send_video_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    video = await _resolve_media(arguments.get("video"))
    sent = await bot.send_video(
        chat_id=_chat_id(context, arguments),
        video=video,
        caption=arguments.get("caption"),
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_send_animation_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    animation = await _resolve_media(arguments.get("animation"))
    sent = await bot.send_animation(
        chat_id=_chat_id(context, arguments),
        animation=animation,
        caption=arguments.get("caption"),
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_send_document_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    document = await _resolve_media(arguments.get("document"))
    sent = await bot.send_document(
        chat_id=_chat_id(context, arguments),
        document=document,
        caption=arguments.get("caption"),
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_send_sticker_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    sticker = await _resolve_media(arguments.get("sticker"))
    sent = await bot.send_sticker(
        chat_id=_chat_id(context, arguments),
        sticker=sticker,
        reply_to_message_id=arguments.get("reply_to_message_id"),
    )
    return {"ok": True, "message_id": sent.message_id, "chat_id": sent.chat.id}


async def telegram_edit_message_text_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    message = await bot.edit_message_text(
        chat_id=_chat_id(context, arguments),
        message_id=arguments["message_id"],
        text=arguments["text"],
    )
    return {"ok": True, "message_id": message.message_id, "chat_id": message.chat.id}


async def telegram_delete_message_handler(context: ToolExecutionContext, arguments: dict[str, Any]) -> dict[str, Any]:
    bot = _get_bot(context)
    await bot.delete_message(chat_id=_chat_id(context, arguments), message_id=arguments["message_id"])
    return {"ok": True, "message_id": arguments["message_id"], "chat_id": _chat_id(context, arguments)}


def build_tools() -> list[ToolDefinition]:
    return [
        ToolDefinition(
            name="telegram_send_message",
            description="Send a plain text message through the active Telegram bot. If chat_id is omitted, the current active chat/DM is used.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "text": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                    "disable_notification": {"type": "boolean"},
                },
                required=["text"],
            ),
            handler=telegram_send_message_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_send_photo",
            description="Send a photo by local path, Telegram file_id, or URL. If chat_id is omitted, the current active chat/DM is used.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "photo": {"type": "string"},
                    "caption": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                },
                required=["photo"],
            ),
            handler=telegram_send_photo_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_send_video",
            description="Send a video by local path, Telegram file_id, or URL. If chat_id is omitted, the current active chat/DM is used.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "video": {"type": "string"},
                    "caption": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                },
                required=["video"],
            ),
            handler=telegram_send_video_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_send_animation",
            description="Send a GIF/animation by local path, Telegram file_id, or URL.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "animation": {"type": "string"},
                    "caption": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                },
                required=["animation"],
            ),
            handler=telegram_send_animation_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_send_document",
            description="Send a document by local path, Telegram file_id, or URL. If chat_id is omitted, the current active chat/DM is used.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "document": {"type": "string"},
                    "caption": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                },
                required=["document"],
            ),
            handler=telegram_send_document_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_send_sticker",
            description="Send a sticker by local path or Telegram file_id.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "sticker": {"type": "string"},
                    "reply_to_message_id": {"type": "integer"},
                },
                required=["sticker"],
            ),
            handler=telegram_send_sticker_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_edit_message_text",
            description="Edit a previously sent Telegram message.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "message_id": {"type": "integer"},
                    "text": {"type": "string"},
                },
                required=["message_id", "text"],
            ),
            handler=telegram_edit_message_text_handler,
            owner_only=True,
            destructive=True,
        ),
        ToolDefinition(
            name="telegram_delete_message",
            description="Delete a Telegram message by chat and message id.",
            parameters=object_schema(
                {
                    "chat_id": {"type": ["string", "integer"]},
                    "message_id": {"type": "integer"},
                },
                required=["message_id"],
            ),
            handler=telegram_delete_message_handler,
            owner_only=True,
            destructive=True,
        ),
    ]
