"""Telegram Bot API proxy tool.

Two HTTP clients are used:
- api_url  (Django)   → bot management (register, list, deactivate, set_webhook)
- telegram_url (FastAPI telegram_service) → proxy calls (send, call any method)
"""

import logging
from ..._config import SDKConfig
from ..._api.client import (
    BaseResource, AsyncBaseResource,
    SyncTelegramTelegramAPI, TelegramTelegramAPI,
)
from ..._api.generated.telegram.telegram__api__telegram.models import (
    TelegramRegisterBotRequest as RegisterBotRequest,
    TelegramSetWebhookRequest as SetWebhookRequest,
)
from ._types import BotInfo, TelegramResult

logger = logging.getLogger(__name__)


class TelegramResource(BaseResource):
    """Telegram Bot API proxy — sync.

    Example:
        ```python
        from sdkrouter import SDKRouter

        client = SDKRouter(api_key="sk_live_xxx")

        # Register a bot (once)
        bot = client.telegram.register(
            alias="support_bot",
            token="7123456789:AAF...",
            callback_url="https://myapp.com/updates",
        )

        # Send a message
        client.telegram.send_message(
            bot="support_bot",
            chat_id=123456,
            text="Hello!",
        )

        # Any Telegram API method
        client.telegram.call("support_bot", "answerCallbackQuery",
                             callback_query_id="abc", text="Done!")
        ```
    """

    def __init__(self, config: SDKConfig):
        super().__init__(config)                              # api_url for CRUD
        self._api = SyncTelegramTelegramAPI(self._http_client)
        # Separate client pointing at telegram_service
        self._tg_client = self._factory.create_sync_client(use_telegram_url=True)

    # ── Bot management (Django API) ──────────────────────────────────────────

    def register(self, alias: str, token: str, callback_url: str = "") -> BotInfo:
        """Register a Telegram bot. Token is encrypted server-side, never returned."""
        result = self._api.bots_register_create(
            RegisterBotRequest(alias=alias, token=token, callback_url=callback_url)
        )
        return BotInfo.model_validate(result.model_dump())

    def list_bots(self) -> list[BotInfo]:
        """List all bots registered under the current API key."""
        result = self._api.bots_list_list()
        items = result if isinstance(result, list) else getattr(result, "results", [result])
        return [BotInfo.model_validate(b.model_dump()) for b in items]

    def set_webhook(self, bot: str, callback_url: str) -> BotInfo:
        """Update the callback URL for incoming updates."""
        result = self._api.bots_set_webhook_create(
            bot, SetWebhookRequest(callback_url=callback_url)
        )
        return BotInfo.model_validate(result.model_dump())

    def deactivate(self, bot: str) -> BotInfo:
        """Deactivate a bot (proxy calls rejected, registration preserved)."""
        resp = self._http_client.post(f"/api/telegram/bots/{bot}/deactivate/")
        resp.raise_for_status()
        return BotInfo.model_validate(resp.json())

    def delete(self, bot: str) -> None:
        """Permanently delete a bot (removes webhook from Telegram first)."""
        self._api.bots_destroy(bot)

    # ── Proxy calls (telegram_service) ──────────────────────────────────────

    def call(self, bot: str, method: str, **params) -> TelegramResult:
        """Call any Telegram Bot API method via the proxy.

        Args:
            bot: Bot alias (registered via register()).
            method: Telegram API method name (e.g. 'sendMessage', 'getMe').
            **params: Method parameters forwarded to Telegram.

        Returns:
            TelegramResult with ok and result fields.

        Example:
            client.telegram.call("my_bot", "sendMessage", chat_id=123, text="Hi")
        """
        resp = self._tg_client.post(f"/v1/telegram/{bot}/{method}", json=params)
        resp.raise_for_status()
        return TelegramResult.model_validate(resp.json())

    # ── Convenience shortcuts ────────────────────────────────────────────────

    def send_message(
        self, bot: str, chat_id: int | str, text: str, *,
        parse_mode: str = "HTML",
        reply_to_message_id: int | None = None,
        disable_notification: bool = False,
        **kwargs,
    ) -> TelegramResult:
        """Send a text message."""
        return self.call(
            bot, "sendMessage",
            chat_id=chat_id, text=text, parse_mode=parse_mode,
            reply_to_message_id=reply_to_message_id,
            disable_notification=disable_notification,
            **kwargs,
        )

    def send_photo(self, bot: str, chat_id: int | str, photo: str,
                   caption: str = "", **kwargs) -> TelegramResult:
        """Send a photo by URL or file_id."""
        return self.call(bot, "sendPhoto", chat_id=chat_id, photo=photo,
                         caption=caption, **kwargs)

    def send_document(self, bot: str, chat_id: int | str, document: str,
                      caption: str = "", **kwargs) -> TelegramResult:
        """Send a document by URL or file_id."""
        return self.call(bot, "sendDocument", chat_id=chat_id, document=document,
                         caption=caption, **kwargs)

    def get_me(self, bot: str) -> TelegramResult:
        """Get bot info from Telegram."""
        return self.call(bot, "getMe")

    def get_updates(self, bot: str, offset: int | None = None,
                    limit: int = 100, timeout: int = 0) -> list[dict]:
        """Get pending updates via long polling (dev use). Prefer webhooks in prod."""
        result = self.call(bot, "getUpdates",
                           offset=offset, limit=limit, timeout=timeout)
        return result.result or []


class AsyncTelegramResource(AsyncBaseResource):
    """Telegram Bot API proxy — async."""

    def __init__(self, config: SDKConfig):
        super().__init__(config)
        self._api = TelegramTelegramAPI(self._http_client)
        self._tg_client = self._factory.create_async_client(use_telegram_url=True)

    async def register(self, alias: str, token: str, callback_url: str = "") -> BotInfo:
        result = await self._api.bots_register_create(
            RegisterBotRequest(alias=alias, token=token, callback_url=callback_url)
        )
        return BotInfo.model_validate(result.model_dump())

    async def list_bots(self) -> list[BotInfo]:
        result = await self._api.bots_list_list()
        items = result if isinstance(result, list) else getattr(result, "results", [result])
        return [BotInfo.model_validate(b.model_dump()) for b in items]

    async def set_webhook(self, bot: str, callback_url: str) -> BotInfo:
        result = await self._api.bots_set_webhook_create(
            bot, SetWebhookRequest(callback_url=callback_url)
        )
        return BotInfo.model_validate(result.model_dump())

    async def deactivate(self, bot: str) -> BotInfo:
        resp = await self._http_client.post(f"/api/telegram/bots/{bot}/deactivate/")
        resp.raise_for_status()
        return BotInfo.model_validate(resp.json())

    async def delete(self, bot: str) -> None:
        await self._api.bots_destroy(bot)

    async def call(self, bot: str, method: str, **params) -> TelegramResult:
        resp = await self._tg_client.post(f"/v1/telegram/{bot}/{method}", json=params)
        resp.raise_for_status()
        return TelegramResult.model_validate(resp.json())

    async def send_message(self, bot: str, chat_id: int | str, text: str,
                           **kwargs) -> TelegramResult:
        return await self.call(bot, "sendMessage", chat_id=chat_id, text=text, **kwargs)

    async def send_photo(self, bot: str, chat_id: int | str, photo: str,
                         **kwargs) -> TelegramResult:
        return await self.call(bot, "sendPhoto", chat_id=chat_id, photo=photo, **kwargs)

    async def send_document(self, bot: str, chat_id: int | str, document: str,
                            **kwargs) -> TelegramResult:
        return await self.call(bot, "sendDocument", chat_id=chat_id, document=document, **kwargs)

    async def get_me(self, bot: str) -> TelegramResult:
        return await self.call(bot, "getMe")

    async def get_updates(self, bot: str, offset: int | None = None,
                          limit: int = 100, timeout: int = 0) -> list[dict]:
        result = await self.call(bot, "getUpdates",
                                 offset=offset, limit=limit, timeout=timeout)
        return result.result or []


__all__ = [
    "TelegramResource",
    "AsyncTelegramResource",
    "BotInfo",
    "TelegramResult",
]
