"""
Menu builders for Telegram bot inline keyboards.

This module provides functions to create InlineKeyboardMarkup objects
for different menu levels and navigation patterns in the bot.

NOTE: All button texts are plain text WITHOUT emojis/icons as per requirements.

BUTTON WIDTH: Inline keyboard width is determined by the message text width.
To make buttons wider, we pad message text with invisible characters.
"""

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from typing import List, Dict, Optional
from datetime import datetime

# ============================================================================
# IMPORTANT: BUTTON WIDTH CONFIGURATION
# ============================================================================
# Inline keyboard button width is determined by MESSAGE TEXT WIDTH!
# DO NOT REMOVE PADDING - it makes buttons wide like BotFather!
# ============================================================================

# Zero-Width Joiner character - invisible but prevents Telegram from trimming spaces
# This character has ZERO width (invisible) but prevents space trimming
ZERO_WIDTH_JOINER = '\u200D'

# Target character count per line to make buttons VERY WIDE
# Higher value = wider buttons (BotFather uses ~45-50 chars)
# DO NOT DECREASE THIS VALUE - buttons will become narrow!
TARGET_WIDTH = 50  # Increased from 40 to make buttons WIDER

# Enable/disable padding globally (useful for testing)
# KEEP THIS TRUE - disabling makes buttons narrow!
ENABLE_BUTTON_PADDING = True


def _get_current_month_ro() -> str:
    """Get current month name in Romanian."""
    months_ro = {
        1: "Ianuarie", 2: "Februarie", 3: "Martie", 4: "Aprilie",
        5: "Mai", 6: "Iunie", 7: "Iulie", 8: "August",
        9: "Septembrie", 10: "Octombrie", 11: "Noiembrie", 12: "Decembrie"
    }
    now = datetime.now()
    return f"{months_ro[now.month]} {now.year}"


def _pad_line_for_wide_buttons(text: str, target_width: int = TARGET_WIDTH) -> str:
    """
    Pad a single line of text with invisible characters to make inline buttons wider.

    ⚠️ CRITICAL: DO NOT REMOVE THIS FUNCTION - it makes buttons wide!
    The width of InlineKeyboardMarkup buttons is determined by the message text width.
    By padding text with spaces + zero-width joiner, we force wider buttons.

    How it works:
    1. Calculate how many characters needed to reach target_width
    2. Add spaces + Zero-Width Joiner (invisible character)
    3. Result: wider message = wider buttons (like BotFather)

    Args:
        text: The text line to pad
        target_width: Target character count (default 50 for VERY WIDE buttons)

    Returns:
        Padded text with invisible characters (user sees normal text, Telegram sees wider text)
    """
    current_length = len(text)
    if current_length >= target_width:
        return text

    # ⚠️ DO NOT REMOVE: Add spaces + zero-width joiner at the end
    # This makes buttons WIDE without changing visible text!
    padding_needed = target_width - current_length
    padding = ' ' * padding_needed + ZERO_WIDTH_JOINER

    return text + padding


def pad_message_for_wide_buttons(message: str, target_width: int = TARGET_WIDTH, force: bool = False) -> str:
    """
    Pad all lines in a message to make inline keyboard buttons wider.

    ⚠️ CRITICAL: DO NOT REMOVE THIS FUNCTION - it makes buttons wide!
    This is the MAIN function that applies padding to ALL messages with keyboards.

    Why we need this:
    - Telegram determines button width based on MESSAGE TEXT width
    - Short messages = narrow buttons
    - Wide messages (with invisible padding) = WIDE buttons like BotFather

    Args:
        message: Multi-line message text
        target_width: Target character count per line (default 50)
        force: Force padding even if ENABLE_BUTTON_PADDING is False

    Returns:
        Message with all lines padded (if enabled or forced)
    """
    # ⚠️ DO NOT REMOVE: Check if padding is enabled
    if not ENABLE_BUTTON_PADDING and not force:
        return message

    # ⚠️ DO NOT REMOVE: Apply padding to each line
    lines = message.split('\n')
    padded_lines = [_pad_line_for_wide_buttons(line, target_width) for line in lines]
    return '\n'.join(padded_lines)


def format_response_with_company(
    content: str,
    company_name: Optional[str] = None,
    apply_padding: bool = True
) -> str:
    """
    Format a response with company name at the top (simplified format).

    ⚠️ IMPORTANT: Applies padding by default to make buttons WIDE!

    Format:
    Company Name

    [Content]

    Args:
        content: The main content text
        company_name: Company name to show at top (if None, just returns content)
        apply_padding: Whether to apply invisible padding for wider buttons (default TRUE)

    Returns:
        Formatted response with company name header AND padding for wide buttons
    """
    if company_name:
        message = f"{company_name}\n\n{content}"
    else:
        message = content

    # ⚠️ DO NOT REMOVE: Apply padding to make inline keyboard buttons WIDE!
    # Without this, buttons become narrow like before
    if apply_padding:
        message = pad_message_for_wide_buttons(message)

    return message


def get_menu_message(
    company_name: Optional[str] = None,
    company_cui: Optional[str] = None,
    apply_padding: bool = True
) -> str:
    """
    Get the menu message text with company details (simplified format).

    ⚠️ IMPORTANT: Applies padding by default to make menu buttons WIDE!

    Format without labels - just values:
    - Line 1: Company name
    - Line 2: CUI
    - Line 3: Accounting month

    Args:
        company_name: Active company name
        company_cui: Company fiscal code (CUI)
        apply_padding: Whether to apply invisible padding for wider buttons (default TRUE)

    Returns:
        Formatted message text for menu WITH padding for wide buttons
    """
    if company_name:
        # Simplified format: just values, no labels
        message = f"{company_name}\n"
        if company_cui:
            message += f"{company_cui}\n"
        message += f"{_get_current_month_ro()}"
    else:
        # No company selected - just prompt
        message = "Selectează o companie pentru a continua"

    # ⚠️ DO NOT REMOVE: Apply padding to make inline keyboard buttons WIDE!
    # This makes buttons look like BotFather (wide, not narrow)
    if apply_padding:
        message = pad_message_for_wide_buttons(message)

    return message


def create_main_menu(
    company_name: Optional[str] = None,
    company_cui: Optional[str] = None,
    is_authenticated: bool = True,
    cache_enabled: Optional[bool] = None
) -> InlineKeyboardMarkup:
    """
    Create main menu keyboard (Level 1) with financial options.

    Layout: Full-width buttons with company selection at top

    Args:
        company_name: Active company name, or None if no company selected
        company_cui: Company fiscal code (CUI), or None
        is_authenticated: Whether user is authenticated (affects Login/Logout button)
        cache_enabled: Cache state for user (True=ON, False=OFF, None=unknown)

    Returns:
        InlineKeyboardMarkup with main menu buttons
    """
    keyboard = []

    # Only show financial menu if authenticated
    if is_authenticated:
        # Row 1: Company selection (full width, single line - InlineKeyboardButton doesn't support multiline)
        if company_name:
            # Short company name for button (CUI and month will be shown in message text)
            # Truncate long names to fit in button
            max_length = 35
            display_name = company_name if len(company_name) <= max_length else company_name[:max_length-3] + "..."

            keyboard.append([
                InlineKeyboardButton(
                    f"{display_name}",
                    callback_data="menu:select_company"
                )
            ])
        else:
            keyboard.append([
                InlineKeyboardButton(
                    "Selectare Companie",
                    callback_data="menu:select_company"
                )
            ])

        # Rows 2-4: Financial options (compact layout with unified Trezorerie button)
        keyboard.extend([
            [
                InlineKeyboardButton("Sold Companie", callback_data="menu:sold"),
                InlineKeyboardButton("Trezorerie", callback_data="menu:trezorerie")
            ],
            [
                InlineKeyboardButton("Sold Clienti", callback_data="menu:clienti"),
                InlineKeyboardButton("Sold Furnizori", callback_data="menu:furnizori")
            ],
            [
                InlineKeyboardButton("Evolutie Incasari", callback_data="menu:evolutie")
            ]
        ])

    # Row 5: Cache options (2 buttons per row, only if authenticated)
    if is_authenticated:
        # Dynamic cache toggle button showing current state
        if cache_enabled is None:
            cache_button_text = "Toggle Cache"
        elif cache_enabled:
            cache_button_text = "Cache: ON"
        else:
            cache_button_text = "Cache: OFF"

        keyboard.append([
            InlineKeyboardButton(cache_button_text, callback_data="menu:togglecache"),
            InlineKeyboardButton("Clear Cache", callback_data="menu:clearcache")
        ])

    # Row 6: Help/Logout buttons (authenticated) or Login button (non-authenticated)
    if is_authenticated:
        keyboard.append([
            InlineKeyboardButton("Help", callback_data="action:help"),
            InlineKeyboardButton("Logout", callback_data="action:logout")
        ])
    else:
        keyboard.append([
            InlineKeyboardButton("Login", callback_data="action:login")
        ])

    return InlineKeyboardMarkup(keyboard)


def create_action_buttons(current_view: str, show_export: bool = True, show_back: bool = False, show_refresh: bool = True) -> InlineKeyboardMarkup:
    """
    Create action buttons for responses (Refresh, Export, Back, Menu).

    Layout (buttons made wide by message text padding):
        [Refresh] [Export]  (if show_refresh=True and show_export=True)
        [Refresh]           (if show_refresh=True and show_export=False)
        [Înapoi]            (if show_back=True, full width)
        [Menu]              (full width, always shown)

    Args:
        current_view: View identifier for refresh callback (e.g., "sold", "clienti")
        show_export: Whether to show Export button
        show_back: Whether to show Back button to list
        show_refresh: Whether to show Refresh button

    Returns:
        InlineKeyboardMarkup with action buttons
    """
    keyboard = []

    # Row 1: Refresh and optionally Export (only if show_refresh is True)
    if show_refresh:
        if show_export:
            keyboard.append([
                InlineKeyboardButton("Refresh", callback_data=f"action:refresh:{current_view}"),
                InlineKeyboardButton("Export", callback_data=f"action:export:{current_view}")
            ])
        else:
            keyboard.append([
                InlineKeyboardButton("Refresh", callback_data=f"action:refresh:{current_view}")
            ])

    # Row 2: Back to List (if show_back is True)
    if show_back:
        # Determine back callback based on current view
        # ✅ FIX: Handle detail views (client_detail:name, supplier_detail:name)
        if current_view.startswith("client_detail:"):
            back_callback = "menu:clienti"  # Back to client list
        elif current_view.startswith("supplier_detail:"):
            back_callback = "menu:furnizori"  # Back to supplier list
        elif current_view == "clienti":
            back_callback = "clients_page:0"  # Match handlers.py:1689
        elif current_view == "furnizori":
            back_callback = "suppliers_page:0"  # Match handlers.py:1721
        else:
            back_callback = "action:menu"  # Fallback to menu

        keyboard.append([
            InlineKeyboardButton("« Înapoi", callback_data=back_callback)
        ])

    # Row 3: Back to Menu (full width)
    keyboard.append([
        InlineKeyboardButton("Meniu Principal", callback_data="action:menu")
    ])

    return InlineKeyboardMarkup(keyboard)


def create_client_list_keyboard(clients: List[Dict], max_items: int = 10, page: int = 0) -> InlineKeyboardMarkup:
    """
    Create client list keyboard (Level 2) with client buttons and pagination.

    Layout: 1 column for clients, pagination controls, 2 columns for navigation

    Args:
        clients: List of client dicts with keys: id, name, balance
        max_items: Maximum number of clients per page (default: 10)
        page: Current page number (0-indexed)

    Returns:
        InlineKeyboardMarkup with client list buttons and pagination
    """
    keyboard = []

    # Sort clients alphabetically by name
    sorted_clients = sorted(clients, key=lambda x: x.get('name', '').lower())

    # Calculate pagination
    total_clients = len(sorted_clients)
    total_pages = (total_clients + max_items - 1) // max_items  # Ceiling division
    start_idx = page * max_items
    end_idx = min(start_idx + max_items, total_clients)

    # Display clients for current page
    display_clients = sorted_clients[start_idx:end_idx]

    # Add client buttons (1 per row)
    for client in display_clients:
        client_name = client.get('name', 'N/A')
        balance = client.get('balance', 0)

        # Format balance with thousands separator
        balance_str = f"{balance:,.0f}" if balance else "0"

        button_text = f"{client_name} - {balance_str} RON"

        # Limit callback_data to 64 bytes (Telegram limit)
        # Use only first 40 chars of name to stay within limit
        safe_name = client_name[:40] if len(client_name) > 40 else client_name

        keyboard.append([
            InlineKeyboardButton(
                button_text,
                callback_data=f"details:client:{safe_name}:0"  # name:page
            )
        ])

    # Pagination controls (only if more than one page)
    if total_pages > 1:
        nav_buttons = []

        # Previous button
        if page > 0:
            nav_buttons.append(
                InlineKeyboardButton("< Anterior", callback_data=f"clients_page:{page-1}")
            )

        # Page indicator (non-clickable)
        nav_buttons.append(
            InlineKeyboardButton(f"Pagina {page+1}/{total_pages}", callback_data="noop")
        )

        # Next button
        if page < total_pages - 1:
            nav_buttons.append(
                InlineKeyboardButton("Următor >", callback_data=f"clients_page:{page+1}")
            )

        keyboard.append(nav_buttons)

    # Navigation row: Back button only
    keyboard.append([
        InlineKeyboardButton("< Înapoi", callback_data="action:menu")
    ])

    return InlineKeyboardMarkup(keyboard)


def create_supplier_list_keyboard(suppliers: List[Dict], max_items: int = 10, page: int = 0) -> InlineKeyboardMarkup:
    """
    Create supplier list keyboard (Level 2) with supplier buttons and pagination.

    Layout: 1 column for suppliers, pagination controls, 2 columns for navigation

    Args:
        suppliers: List of supplier dicts with keys: id, name, balance
        max_items: Maximum number of suppliers per page (default: 10)
        page: Current page number (0-indexed)

    Returns:
        InlineKeyboardMarkup with supplier list buttons and pagination
    """
    keyboard = []

    # Sort suppliers alphabetically by name
    sorted_suppliers = sorted(suppliers, key=lambda x: x.get('name', '').lower())

    # Calculate pagination
    total_suppliers = len(sorted_suppliers)
    total_pages = (total_suppliers + max_items - 1) // max_items  # Ceiling division
    start_idx = page * max_items
    end_idx = min(start_idx + max_items, total_suppliers)

    # Display suppliers for current page
    display_suppliers = sorted_suppliers[start_idx:end_idx]

    # Add supplier buttons (1 per row)
    for supplier in display_suppliers:
        supplier_name = supplier.get('name', 'N/A')
        balance = supplier.get('balance', 0)

        # Format balance with thousands separator
        balance_str = f"{balance:,.0f}" if balance else "0"

        button_text = f"{supplier_name} - {balance_str} RON"

        # Limit callback_data to 64 bytes (Telegram limit)
        # Use only first 40 chars of name to stay within limit
        safe_name = supplier_name[:40] if len(supplier_name) > 40 else supplier_name

        keyboard.append([
            InlineKeyboardButton(
                button_text,
                callback_data=f"details:supplier:{safe_name}:0"  # name:page
            )
        ])

    # Pagination controls (only if more than one page)
    if total_pages > 1:
        nav_buttons = []

        # Previous button
        if page > 0:
            nav_buttons.append(
                InlineKeyboardButton("< Anterior", callback_data=f"suppliers_page:{page-1}")
            )

        # Page indicator (non-clickable)
        nav_buttons.append(
            InlineKeyboardButton(f"Pagina {page+1}/{total_pages}", callback_data="noop")
        )

        # Next button
        if page < total_pages - 1:
            nav_buttons.append(
                InlineKeyboardButton("Următor >", callback_data=f"suppliers_page:{page+1}")
            )

        keyboard.append(nav_buttons)

    # Navigation row: Back button only
    keyboard.append([
        InlineKeyboardButton("< Înapoi", callback_data="action:menu")
    ])

    return InlineKeyboardMarkup(keyboard)


def create_invoice_list_keyboard(
    invoices: List[Dict],
    partner_type: str,
    partner_name: str,
    max_items: int = 10,
    page: int = 0
) -> InlineKeyboardMarkup:
    """
    Create invoice list keyboard (Level 3) with invoice buttons and pagination.

    Layout: 1 column for invoices, pagination controls, 2 columns for navigation

    Args:
        invoices: List of invoice dicts with keys: id, number, amount, status
        partner_type: "CLIENTI" or "FURNIZORI"
        partner_name: Client/supplier name (for back navigation)
        max_items: Maximum number of invoices per page (default: 10)
        page: Current page number (0-indexed)

    Returns:
        InlineKeyboardMarkup with invoice list buttons and pagination
    """
    keyboard = []

    # Limit partner_name to 30 chars for Telegram callback_data limit (64 bytes)
    safe_partner_name = partner_name[:30] if len(partner_name) > 30 else partner_name

    # Calculate pagination
    total_invoices = len(invoices)
    total_pages = (total_invoices + max_items - 1) // max_items  # Ceiling division
    start_idx = page * max_items
    end_idx = min(start_idx + max_items, total_invoices)

    # Display invoices for current page
    display_invoices = invoices[start_idx:end_idx]

    # Add invoice buttons (1 per row)
    for invoice in display_invoices:
        invoice_id = invoice.get('id', 0)
        invoice_number = invoice.get('number', 'N/A')
        amount = invoice.get('amount', 0)
        status = invoice.get('status', 'unknown')

        # Format amount with thousands separator
        amount_str = f"{amount:,.0f}" if amount else "0"

        # Status text indicator (no emojis)
        status_text = "[NEPLATIT]" if status in ['unpaid', 'overdue'] else "[PLATIT]"

        button_text = f"{status_text} {invoice_number} - {amount_str} RON"
        keyboard.append([
            InlineKeyboardButton(
                button_text,
                callback_data=f"invoice:{partner_type}:{invoice_id}"
            )
        ])

    # Pagination controls (only if more than one page)
    if total_pages > 1:
        nav_buttons = []

        # Previous button
        if page > 0:
            nav_buttons.append(
                InlineKeyboardButton("< Anterior", callback_data=f"invoices_page:{partner_type}:{safe_partner_name}:{page-1}")
            )

        # Page indicator (non-clickable)
        nav_buttons.append(
            InlineKeyboardButton(f"Pagina {page+1}/{total_pages}", callback_data="noop")
        )

        # Next button
        if page < total_pages - 1:
            nav_buttons.append(
                InlineKeyboardButton("Următor >", callback_data=f"invoices_page:{partner_type}:{safe_partner_name}:{page+1}")
            )

        keyboard.append(nav_buttons)

    # Navigation row: Back and Export (2 buttons per row)
    back_target = "clienti" if partner_type == "CLIENTI" else "furnizori"
    keyboard.append([
        InlineKeyboardButton("< Înapoi", callback_data=f"nav:back:{back_target}"),
        InlineKeyboardButton("Export", callback_data=f"action:export:{partner_type.lower()}")
    ])

    return InlineKeyboardMarkup(keyboard)


def create_navigation_buttons(back_to: str) -> InlineKeyboardMarkup:
    """
    Create simple navigation buttons (just Back button).

    Args:
        back_to: Target location identifier (e.g., "menu", "clienti", "furnizori")

    Returns:
        InlineKeyboardMarkup with navigation button
    """
    keyboard = [
        [
            InlineKeyboardButton(
                f"< Înapoi la {back_to}",
                callback_data=f"nav:back:{back_to}"
            )
        ]
    ]

    return InlineKeyboardMarkup(keyboard)
