from typing import Dict

from typing import Dict, List, Optional, Union
from typing import Dict, List, Optional

class InlineBuilder:
    def __init__(self):
        self.rows: List[Dict] = []

    def row(self, *buttons: Dict) -> "InlineBuilder":
        """
        افزودن یک ردیف دکمه به کیبورد
        حداقل یک دکمه باید داده شود.
        """
        if not buttons:
            raise ValueError("حداقل یک دکمه باید به row داده شود")
        self.rows.append({"buttons": list(buttons)})
        return self
    def button_open_chat(self, id: str , text: str, object_guid: str , object_type: str ="User") -> Dict:
        return {
            "id": id,
            "type": 'Link', 
            "button_text": text,
            "button_link": {
                "type": 'openchat', 
                "open_chat_data": {
                    "object_guid": object_guid,
                    "object_type": object_type 
                }
            }
        }
    def button_join_channel(self, id: str , text: str, username: str, ask_join: bool = False) -> Dict:
        """
        Creates an inline button that prompts the user to join a Rubika channel.

        Args:
            id (str): Unique identifier for the button (used for event handling).
            text (str): The text displayed on the button.
            username (str): The channel username (can be with or without '@').
            ask_join (bool, optional): If True, the user will be prompted with a 
                                    confirmation dialog before joining. 
                                    Defaults to False.

        Returns:
            dict: A dictionary representing the inline button, which can be passed
                to inline keyboard builder methods.

        Example:
            ```python
            from rubka.button import InlineBuilder

            buttons = (
                InlineBuilder()
                .row(
                    InlineBuilder().button_join_channel(
                        id="join_btn",
                        text="Join our channel 📢",
                        username="rubka_library",
                        ask_join=True
                    )
                )
                .build()
            )

            await message.reply_inline(
                text="Please join our channel before using the bot.",
                inline_keypad=buttons
            )
            ```
        """
        return {
            "id": id,
            "type": 'Link', 
            "button_text": text,
            "button_link": {
                "type": 'joinchannel', 
                "joinchannel_data": {
                    "username": username.replace("@", ""),
                    "ask_join": ask_join
                }
            }
        }

    def button_url_link(self, id: str , text: str, url: str) -> Dict:
        """
        Creates an inline button that opens a given URL when clicked.

        Args:
            id (str): Unique identifier for the button (used for event handling if needed).
            text (str): The text displayed on the button.
            url (str): The destination URL that will be opened when the button is clicked.

        Returns:
            dict: A dictionary representing the inline button, which can be passed
                to inline keyboard builder methods.

        Example:
            ```python
            from rubka.button import InlineBuilder

            buttons = (
                InlineBuilder()
                .row(
                    InlineBuilder().button_url_link(
                        id="website_btn",
                        text="Visit our website 🌐",
                        url="https://api-free.ir"
                    )
                )
                .build()
            )

            await message.reply_inline(
                text="Click the button below to visit our website.",
                inline_keypad=buttons
            )
            ```
        """
        return {
            "id": id,
            "type": 'Link', 
            "button_text": text,
            "button_link": {
                "type": 'url', 
                "link_url": url
            }
        }

    def button_simple(self, id: str , text: str) -> Dict:
        return {"id": id, "type": "Simple", "button_text": text}

    def button_selection(self, id: str , text: str, selection: Dict) -> Dict:
        """
        selection: dict با فیلدهای:
         - selection_id (str)
         - search_type (str) [ButtonSelectionSearchEnum: None, Local, Api]
         - get_type (str) [ButtonSelectionGetEnum: Local, Api]
         - items (list of ButtonSelectionItem)
         - is_multi_selection (bool)
         - columns_count (str)
         - title (str)
        """
        return {
            "id": id,
            "type": "Selection",
            "button_text": text,
            "button_selection": selection
        }

    def button_calendar(self, id: str , title: str, type_: str,
                        default_value: Optional[str] = None,
                        min_year: Optional[str] = None,
                        max_year: Optional[str] = None) -> Dict:
        """
        type_: ButtonCalendarTypeEnum = "DatePersian" | "DateGregorian"
        """
        calendar = {
            "title": title,
            "type": type_,
        }
        if default_value:
            calendar["default_value"] = default_value
        if min_year:
            calendar["min_year"] = min_year
        if max_year:
            calendar["max_year"] = max_year

        return {
            "id": id,
            "type": "Calendar",
            "button_text": title,
            "button_calendar": calendar
        }

    def button_number_picker(self, id: str , title: str, min_value: str, max_value: str,
                             default_value: Optional[str] = None) -> Dict:
        picker = {
            "title": title,
            "min_value": min_value,
            "max_value": max_value,
        }
        if default_value:
            picker["default_value"] = default_value

        return {
            "id": id,
            "type": "NumberPicker",
            "button_text": title,
            "button_number_picker": picker
        }

    def button_string_picker(self, id: Optional[str], title: Optional[str], items: List[str],
                             default_value: Optional[str] = None) -> Dict:
        picker = {
            "items": items
        }
        if default_value:
            picker["default_value"] = default_value
        if title:
            picker["title"] = title

        return {
            "id": id,
            "type": "StringPicker",
            "button_text": title if title else "انتخاب",
            "button_string_picker": picker
        }

    def button_location(self, id: str , type_: str, location_image_url: str,
                        default_pointer_location: Optional[Dict] = None,
                        default_map_location: Optional[Dict] = None,
                        title: Optional[str] = None) -> Dict:
        """
        type_: ButtonLocationTypeEnum = "Picker" | "View"
        location_image_url: str آدرس عکس دکمه موقعیت
        default_pointer_location و default_map_location هر کدام دیکشنری Location (latitude, longitude)
        """
        loc = {
            "type": type_,
            "location_image_url": location_image_url,
        }
        if default_pointer_location:
            loc["default_pointer_location"] = default_pointer_location
        if default_map_location:
            loc["default_map_location"] = default_map_location
        if title:
            loc["title"] = title

        return {
            "id": id,
            "type": "Location",
            "button_text": title if title else "موقعیت مکانی",
            "button_location": loc
        }

    def button_textbox(self, id: str , title: Optional[str], 
                       type_line: str, type_keypad: str,
                       place_holder: Optional[str] = None,
                       default_value: Optional[str] = None) -> Dict:
        """
        type_line: ButtonTextboxTypeLineEnum = "SingleLine" | "MultiLine"
        type_keypad: ButtonTextboxTypeKeypadEnum = "String" | "Number"
        """
        textbox = {
            "type_line": type_line,
            "type_keypad": type_keypad
        }
        if place_holder:
            textbox["place_holder"] = place_holder
        if default_value:
            textbox["default_value"] = default_value
        if title:
            textbox["title"] = title

        return {
            "id": id,
            "type": "Textbox",
            "button_text": title if title else "متن",
            "button_textbox": textbox
        }

    def button_payment(self, id: str , title: str, amount: int, description: Optional[str] = None) -> Dict:
        """
        نمونه‌ای ساده برای دکمه پرداخت (مقدار و توضیح دلخواه)
        """
        payment = {
            "title": title,
            "amount": amount
        }
        if description:
            payment["description"] = description

        return {
            "id": id,
            "type": "Payment",
            "button_text": title,
            "button_payment": payment
        }

    def button_camera_image(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "CameraImage",
            "button_text": title
        }

    def button_camera_video(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "CameraVideo",
            "button_text": title
        }

    def button_gallery_image(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "GalleryImage",
            "button_text": title
        }

    def button_gallery_video(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "GalleryVideo",
            "button_text": title
        }

    def button_file(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "File",
            "button_text": title
        }

    def button_audio(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "Audio",
            "button_text": title
        }

    def button_record_audio(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "RecordAudio",
            "button_text": title
        }

    def button_my_phone_number(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "MyPhoneNumber",
            "button_text": title
        }

    def button_my_location(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "MyLocation",
            "button_text": title
        }

    def button_link(self, id: str , title: str, url: str) -> Dict:
        return {
            "id": id,
            "type": "Link",
            "button_text": title,
            "url": url
        }

    def button_ask_my_phone_number(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "AskMyPhoneNumber",
            "button_text": title
        }

    def button_ask_location(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "AskLocation",
            "button_text": title
        }
    def create_link_button(self,title: str, url: str):
        return {
            "type": "Link",
            "button_text": title,
            "url": url
        }
    def button_selection_items(
        self,
        id:str,
        button_text: str,
        selection_id: str ,
        title: str,
        items: List[Dict[str, any]],
        search_type: str = "None",
        get_type: str = "Local",
        columns_count: int = 1,
        is_multi_selection: bool = False
    ) -> Dict[str, any]:
        return {
            "id": id,
            "type": "Selection",
            "button_text": button_text,
            "button_selection": {
                "selection_id": selection_id,
                "title": title,
                "search_type": search_type,
                "get_type": get_type,
                "columns_count": str(columns_count),
                "is_multi_selection": is_multi_selection,
                "items": items
            }
        }

    def button_barcode(self, id: str , title: str) -> Dict:
        return {
            "id": id,
            "type": "Barcode",
            "button_text": title
        }

    def build(self) -> Dict:
        return {"rows": self.rows}
class ChatKeypadBuilder(InlineBuilder):
    """
    Chat Keypad Builder for creating chat buttons.

    This class uses the Builder pattern to add multiple rows of buttons
    and build the final keypad structure.

    Example:
    --------
    ```python
    keyboard = ChatKeypadBuilder()
    keypad = (
        keyboard
        .row(
            keyboard.button(text="test")
        )
        .build()
    )
    # Resulting keypad structure:
    # {
    #     "rows": [{"buttons": [{"id": "None", "type": "Simple", "button_text": "test"}]}],
    #     "resize_keyboard": True,
    #     "on_time_keyboard": False
    # }
    """

    def __init__(self):
        """
        Initializes the builder with an empty list of rows.
        """
        self.rows: List[Dict[str, List[Dict[str, str]]]] = []

    def row(self, *buttons: Dict[str, str]) -> "ChatKeypadBuilder":
        """
        Adds a row of buttons to the keypad.

        Parameters
        ----------
        *buttons : Dict[str, str]
            One or more dictionaries representing buttons.

        Returns
        -------
        ChatKeypadBuilder
            Returns self for method chaining.
        """
        self.rows.append({"buttons": list(buttons)})
        return self

    def button(self, id: str , text: str, type: str = "Simple") -> Dict[str, str]:
        return {"id": id, "type": type, "button_text": text}

    def build(
        self,
        resize_keyboard: bool = True,
        on_time_keyboard: bool = False
    ) -> Dict[str, object]:
        """
        Builds the final keypad structure.

        Parameters
        ----------
        resize_keyboard : bool, default True
            Whether the keyboard should adjust its size based on button count.
        on_time_keyboard : bool, default False
            Whether the keyboard should appear temporarily.

        Returns
        -------
        dict
            The final dictionary representing the keypad.
        """
        return {
            "rows": self.rows,
            "resize_keyboard": resize_keyboard,
            "on_time_keyboard": on_time_keyboard
        }
