import requests
from typing import List, Optional, Dict, Any, Literal
from .exceptions import APIRequestError
from .logger import logger

API_URL = "https://botapi.rubika.ir/v3"

class Robot:
    """
    Main class to interact with Rubika Bot API.
    Initialized with bot token.
    """

    def __init__(self, token: str):
        self.token = token
        self.session = requests.Session()
        logger.info(f"Initialized RubikaBot with token: {token[:8]}***")

    def _post(self, method: str, data: Dict[str, Any]) -> Dict[str, Any]:
        url = f"{API_URL}/{self.token}/{method}"
        try:
            response = self.session.post(url, json=data, timeout=10)
            response.raise_for_status()
            json_resp = response.json()
            logger.debug(f"API Response from {method}: {json_resp}")
            return json_resp
        except requests.RequestException as e:
            logger.error(f"API request failed: {e}")
            raise APIRequestError(f"API request failed: {e}") from e

    def get_me(self) -> Dict[str, Any]:
        """Get info about the bot itself."""
        return self._post("getMe", {})

    def send_message(
        self,
        chat_id: str,
        text: str,
        chat_keypad: Optional[Dict[str, Any]] = None,
        inline_keypad: Optional[Dict[str, Any]] = None,
        disable_notification: bool = False,
        reply_to_message_id: Optional[str] = None,
        chat_keypad_type: Optional[Literal["New", "Removed"]] = None
    ) -> Dict[str, Any]:
        """
        Send a text message to a chat.
        """
        payload = {
            "chat_id": chat_id,
            "text": text,
            "disable_notification": disable_notification
        }
        if chat_keypad:
            payload["chat_keypad"] = chat_keypad
        if inline_keypad:
            payload["inline_keypad"] = inline_keypad
        if reply_to_message_id:
            payload["reply_to_message_id"] = reply_to_message_id
        if chat_keypad_type:
            payload["chat_keypad_type"] = chat_keypad_type

        return self._post("sendMessage", payload)

    def send_poll(
        self,
        chat_id: str,
        question: str,
        options: List[str]
    ) -> Dict[str, Any]:
        """
        Send a poll to a chat.
        """
        return self._post("sendPoll", {
            "chat_id": chat_id,
            "question": question,
            "options": options
        })

    def send_location(
        self,
        chat_id: str,
        latitude: str,
        longitude: str,
        disable_notification: bool = False,
        inline_keypad: Optional[Dict[str, Any]] = None,
        reply_to_message_id: Optional[str] = None,
        chat_keypad_type: Optional[Literal["New", "Removed"]] = None
    ) -> Dict[str, Any]:
        """
        Send a location to a chat.
        """
        payload = {
            "chat_id": chat_id,
            "latitude": latitude,
            "longitude": longitude,
            "disable_notification": disable_notification,
            "inline_keypad": inline_keypad,
            "reply_to_message_id": reply_to_message_id,
            "chat_keypad_type": chat_keypad_type
        }
        # Remove None values
        payload = {k: v for k, v in payload.items() if v is not None}
        return self._post("sendLocation", payload)

    def send_contact(
        self,
        chat_id: str,
        first_name: str,
        last_name: str,
        phone_number: str
    ) -> Dict[str, Any]:
        """
        Send a contact to a chat.
        """
        return self._post("sendContact", {
            "chat_id": chat_id,
            "first_name": first_name,
            "last_name": last_name,
            "phone_number": phone_number
        })

    def get_chat(self, chat_id: str) -> Dict[str, Any]:
        """Get chat info."""
        return self._post("getChat", {"chat_id": chat_id})

    def get_updates(
        self,
        offset_id: Optional[str] = None,
        limit: Optional[int] = None
    ) -> Dict[str, Any]:
        """Get updates."""
        data = {}
        if offset_id:
            data["offset_id"] = offset_id
        if limit:
            data["limit"] = limit
        return self._post("getUpdates", data)

    def forward_message(
        self,
        from_chat_id: str,
        message_id: str,
        to_chat_id: str,
        disable_notification: bool = False
    ) -> Dict[str, Any]:
        """Forward a message from one chat to another."""
        return self._post("forwardMessage", {
            "from_chat_id": from_chat_id,
            "message_id": message_id,
            "to_chat_id": to_chat_id,
            "disable_notification": disable_notification
        })

    def edit_message_text(
        self,
        chat_id: str,
        message_id: str,
        text: str
    ) -> Dict[str, Any]:
        """Edit text of an existing message."""
        return self._post("editMessageText", {
            "chat_id": chat_id,
            "message_id": message_id,
            "text": text
        })

    def edit_inline_keypad(
        self,
        chat_id: str,
        message_id: str,
        inline_keypad: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Edit inline keypad of a message."""
        return self._post("editInlineKeypad", {
            "chat_id": chat_id,
            "message_id": message_id,
            "inline_keypad": inline_keypad
        })

    def delete_message(self, chat_id: str, message_id: str) -> Dict[str, Any]:
        """Delete a message from chat."""
        return self._post("deleteMessage", {
            "chat_id": chat_id,
            "message_id": message_id
        })

    def set_commands(self, bot_commands: List[Dict[str, str]]) -> Dict[str, Any]:
        """Set bot commands."""
        return self._post("setCommands", {"bot_commands": bot_commands})

    def update_bot_endpoint(self, url: str, type: str) -> Dict[str, Any]:
        """Update bot endpoint (Webhook or Polling)."""
        return self._post("updateBotEndpoints", {
            "url": url,
            "type": type
        })

    def remove_keypad(self, chat_id: str) -> Dict[str, Any]:
        """Remove chat keypad."""
        return self._post("editChatKeypad", {
            "chat_id": chat_id,
            "chat_keypad_type": "Removed"
        })

    def edit_chat_keypad(self, chat_id: str, chat_keypad: Dict[str, Any]) -> Dict[str, Any]:
        """Edit or add new chat keypad."""
        return self._post("editChatKeypad", {
            "chat_id": chat_id,
            "chat_keypad_type": "New",
            "chat_keypad": chat_keypad
        })
