"""
Telegram Bot Handlers for ROA2WEB ERP Assistant

This module implements all message and command handlers for the Telegram bot.
Handles user interactions, authentication, and routes messages to Claude Agent.
"""

import logging
from typing import Optional, Dict, Any
from io import BytesIO

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ContextTypes
from telegram.constants import ParseMode

from backend.modules.telegram.auth.linking import (
    link_telegram_account,
    check_user_linked,
    get_user_auth_data,
    get_user_companies
)
from backend.modules.telegram.agent.session import get_session_manager
from backend.modules.telegram.db.operations import update_user_last_active
from backend.modules.telegram.api.client import get_backend_client

logger = logging.getLogger(__name__)


# ============================================================================
# COMMAND HANDLERS
# ============================================================================

async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /start command.

    Handles two cases:
    1. /start <auth_code> - Link Telegram account to Oracle account
    2. /start - Show welcome message and instructions

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user = update.effective_user
        telegram_user_id = telegram_user.id
        args = context.args  # Command arguments

        logger.info(f"/start command from user {telegram_user_id} (@{telegram_user.username})")

        # Case 1: /start <auth_code> - Link account
        if args and len(args) > 0:
            auth_code = args[0].upper()
            logger.info(f"Attempting to link user {telegram_user_id} with code {auth_code}")

            # ȘTERGE mesajul utilizatorului imediat (chat curat)
            try:
                await update.message.delete()
            except Exception as e:
                logger.warning(f"Could not delete /start message: {e}")

            # Check dacă user-ul a apăsat pe "Login din Web App" înainte
            web_login_msg_id = context.user_data.get('web_login_message_id')

            if web_login_msg_id:
                # EDITEAZĂ mesajul existent cu "Login din Web App"
                try:
                    await context.bot.edit_message_text(
                        chat_id=update.effective_chat.id,
                        message_id=web_login_msg_id,
                        text="Conectare cont...",
                        parse_mode=ParseMode.MARKDOWN
                    )
                    # IMPORTANT: NU ștergem message_id - îl păstrăm pentru editări ulterioare
                except Exception as e:
                    logger.warning(f"Could not edit web_login message: {e}")
                    # Fallback: creează mesaj nou dacă editarea a eșuat
                    web_login_msg_id = None

            # Dacă nu avem mesaj de editat, creăm unul nou
            if not web_login_msg_id:
                # Creează mesaj nou și salvează ID-ul în context pentru editări ulterioare
                new_msg = await update.effective_chat.send_message(
                    "Conectare cont...",
                    parse_mode=ParseMode.MARKDOWN
                )
                web_login_msg_id = new_msg.message_id
                # Salvează în context pentru consistență
                context.user_data['web_login_message_id'] = web_login_msg_id

            # Attempt linking
            result = await link_telegram_account(telegram_user, auth_code)

            if result:
                # Success!
                username = result['username']
                jwt_token = result['jwt_token']

                # Get session and company info
                session_manager = get_session_manager()
                session = await session_manager.get_or_create_session(telegram_user_id)
                company = session.get_active_company()
                company_name = company['name'] if company else None
                company_cui = company.get('cui') if company else None

                # Get cache status
                cache_enabled = None
                try:
                    from backend.modules.telegram.api.client import get_backend_client
                    client = get_backend_client()
                    async with client:
                        cache_stats = await client.get_cache_stats(jwt_token=jwt_token)
                        cache_enabled = cache_stats.get('user_enabled', True)
                except Exception as e:
                    logger.warning(f"Could not get cache status in /start: {e}")

                from backend.modules.telegram.bot.menus import create_main_menu, pad_message_for_wide_buttons
                keyboard = create_main_menu(company_name, company_cui, is_authenticated=True, cache_enabled=cache_enabled)

                # EDIT message to show menu with company
                if company_name:
                    menu_text = f"{company_name}"
                else:
                    menu_text = "Selectează o companie pentru a continua"

                menu_message = pad_message_for_wide_buttons(menu_text)

                # EDIT the login message (same message throughout the flow)
                await context.bot.edit_message_text(
                    chat_id=update.effective_chat.id,
                    message_id=web_login_msg_id,
                    text=menu_message,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )

                logger.info(f"User {telegram_user_id} successfully linked to {username}")

            else:
                # Failed linking - EDIT message to show error
                await context.bot.edit_message_text(
                    chat_id=update.effective_chat.id,
                    message_id=web_login_msg_id,
                    text="Cod invalid sau expirat\n\n"
                         "Generează un cod nou din aplicația web și trimite:\n"
                         "/start CODUL_TAU",
                    parse_mode=ParseMode.MARKDOWN
                )

                logger.warning(f"Failed to link user {telegram_user_id} with code {auth_code}")

            return

        # Case 2: /start (no args) - Show welcome/instructions
        is_linked = await check_user_linked(telegram_user_id)

        if is_linked:
            # FAZA 3: User is already linked - SHOW MENU
            auth_data = await get_user_auth_data(telegram_user_id)
            username = auth_data.get('username', 'utilizator') if auth_data else 'utilizator'

            # Get active company
            session_manager = get_session_manager()
            session = await session_manager.get_or_create_session(telegram_user_id)
            company = session.get_active_company()

            company_name = company['name'] if company else None
            company_cui = company.get('cui') if company else None

            # Create main menu
            from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
            keyboard = create_main_menu(company_name, company_cui, is_authenticated=True)
            menu_text = get_menu_message(company_name, company_cui)

            await update.message.reply_text(
                f"Bun venit, **{username}**\n\n{menu_text}",
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        else:
            # User not linked - show main menu with Login button
            from backend.modules.telegram.bot.menus import create_main_menu, pad_message_for_wide_buttons

            keyboard = create_main_menu(
                company_name=None,
                company_cui=None,
                is_authenticated=False,  # Not authenticated - shows Login button
                cache_enabled=None
            )

            welcome_text = pad_message_for_wide_buttons(
                "**Bun venit la ROA2WEB Bot**\n\n"
                "Pentru a incepe, te rog să te autentifici.\n\n"
                "Selectează o companie pentru a continua"
            )

            await update.message.reply_text(
                welcome_text,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

    except Exception as e:
        logger.error(f"Error in start_command: {e}", exc_info=True)
        await update.message.reply_text(
            "A aparut o eroare. Te rog incearca din nou mai tarziu."
        )


async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /help command.

    Shows comprehensive help about bot capabilities and usage.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/help command from user {telegram_user_id}")

        help_text = """
**ROA2WEB Bot - Asistent Financiar**

**Cum folosesc bot-ul?**

Dupa conectarea contului, foloseste **butoanele interactive** pentru:

**Operatiuni:**
- Selectare companie activa
- Vizualizare sold si situatie financiara
- Trezorerie (Casa, Banca)
- Sold Clienti cu detalii facturi
- Sold Furnizori cu detalii facturi
- Evolutie incasari/plati lunare

**Navigare:**
- Toate optiunile sunt accesibile prin butoane
- Apasa pe numele companiei pentru a schimba compania activa
- Foloseste butoanele "Refresh" pentru actualizare date
- Foloseste "Meniu Principal" pentru a reveni la menu

**Comenzi disponibile:**
/start - Porneste bot-ul (cu/fara cod de linking)
/menu - Afiseaza meniul principal cu butoane
/help - Acest mesaj de ajutor
/unlink - Deconecteaza contul (securitate)

**Comenzi Cache (optimizare performanta):**
/togglecache - Activeaza/Dezactiveaza cache pentru tine
/clearcache - Sterge cache pentru compania activa
/clearcache all - Sterge tot cache-ul

**Conectare cont:**
1. Loghează-te în aplicația web ROA2WEB
2. Accesează Setări → Telegram Linking
3. Generează cod (valabil 15 minute)
4. Trimite codul în Telegram: `/start CODUL_TAU`

**Securitate:**
Datele sunt protejate prin autentificare JWT.
Poti deconecta oricand cu /unlink.
"""

        await update.message.reply_text(help_text, parse_mode=ParseMode.MARKDOWN)

    except Exception as e:
        logger.error(f"Error in help_command: {e}", exc_info=True)
        await update.message.reply_text(
            "A aparut o eroare. Te rog incearca din nou."
        )


async def clear_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /clear command.

    Clears the active company selection for the user.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/clear command from user {telegram_user_id}")

        # Clear active company from session
        session_manager = get_session_manager()
        session = await session_manager.get_or_create_session(telegram_user_id)
        session.clear_active_company()
        await session_manager.save_session(telegram_user_id)

        await update.message.reply_text(
            "**Companie activa stearsa**\n\n"
            "Foloseste /selectcompany pentru a selecta alta companie.",
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in clear_command: {e}", exc_info=True)
        await update.message.reply_text(
            "A apărut o eroare la ștergerea companiei active."
        )


async def clearcache_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /clearcache command.

    Clears the cache for the current company or all companies.

    Usage:
    - /clearcache - Clear cache for current company
    - /clearcache all - Clear entire cache (all companies)

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/clearcache command from user {telegram_user_id}")

        # Check if user is linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start pentru a conecta contul.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Check if user wants to clear all cache
        clear_all = len(context.args) > 0 and context.args[0].lower() == 'all'

        client = get_backend_client()
        async with client:
            if clear_all:
                # Clear entire cache
                result = await client.client.post(
                    "/api/cache/invalidate",
                    json={},
                    headers=client._get_auth_headers(jwt_token)
                )
                if result.status_code == 200:
                    await update.message.reply_text(
                        "✅ **Cache șters complet**\n\n"
                        "Toate datele cached au fost șterse.",
                        parse_mode=ParseMode.MARKDOWN
                    )
                else:
                    await update.message.reply_text("❌ Eroare la ștergerea cache-ului.")
            else:
                # Get active company
                session_manager = get_session_manager()
                from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
                company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

                if not company:
                    return

                # Clear cache for current company
                result = await client.client.post(
                    "/api/cache/invalidate",
                    json={"company_id": company['id']},
                    headers=client._get_auth_headers(jwt_token)
                )

                if result.status_code == 200:
                    await update.message.reply_text(
                        f"✅ **Cache șters pentru {company['name']}**\n\n"
                        "Datele vor fi reîncărcate la următoarea interogare.",
                        parse_mode=ParseMode.MARKDOWN
                    )
                else:
                    await update.message.reply_text("❌ Eroare la ștergerea cache-ului.")

    except Exception as e:
        logger.error(f"Error in clearcache_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la ștergerea cache-ului.")


async def togglecache_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /togglecache command.

    Toggles cache on/off for the current user.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/togglecache command from user {telegram_user_id}")

        # Check if user is linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start pentru a conecta contul.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        client = get_backend_client()
        async with client:
            # Get current cache stats to determine current state
            stats_response = await client.client.get(
                "/api/cache/stats",
                headers=client._get_auth_headers(jwt_token)
            )

            if stats_response.status_code == 200:
                stats = stats_response.json()
                current_enabled = stats.get('user_cache_enabled', True)

                # Toggle to opposite state
                new_state = not current_enabled

                toggle_response = await client.client.post(
                    "/api/cache/toggle-user",
                    json={"enabled": new_state},
                    headers=client._get_auth_headers(jwt_token)
                )

                if toggle_response.status_code == 200:
                    if new_state:
                        await update.message.reply_text(
                            "✅ **Cache activat**\n\n"
                            "Interogările tale vor folosi cache-ul pentru răspunsuri mai rapide.",
                            parse_mode=ParseMode.MARKDOWN
                        )
                    else:
                        await update.message.reply_text(
                            "⚠️ **Cache dezactivat**\n\n"
                            "Interogările tale vor accesa direct baza de date Oracle.",
                            parse_mode=ParseMode.MARKDOWN
                        )
                else:
                    await update.message.reply_text("❌ Eroare la comutarea cache-ului.")
            else:
                await update.message.reply_text("❌ Eroare la citirea stării cache-ului.")

    except Exception as e:
        logger.error(f"Error in togglecache_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la comutarea cache-ului.")


async def companies_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /companies command.

    Shows list of companies the user has access to.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/companies command from user {telegram_user_id}")

        # Check if user is linked
        is_linked = await check_user_linked(telegram_user_id)

        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\n"
                "Conecteaza-ti contul cu /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get companies
        companies = await get_user_companies(telegram_user_id)

        if not companies:
            await update.message.reply_text(
                "**Nicio companie gasita**\n\n"
                "Contacteaza administratorul pentru permisiuni.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Format companies list
        companies_text = f"**Companiile tale ({len(companies)}):**\n\n"

        for i, comp in enumerate(companies, 1):
            nume = comp.get('nume_firma', 'N/A')
            comp_id = comp.get('id', 'N/A')
            cui = comp.get('cui', 'N/A')

            companies_text += f"{i}. **{nume}**\n"
            companies_text += f"   - ID: {comp_id}\n"
            companies_text += f"   - CUI: {cui}\n\n"

        companies_text += "\nFoloseste /selectcompany pentru a selecta compania activa."

        await update.message.reply_text(companies_text, parse_mode=ParseMode.MARKDOWN)

    except Exception as e:
        logger.error(f"Error in companies_command: {e}", exc_info=True)
        await update.message.reply_text(
            "A aparut o eroare la incarcarea companiilor."
        )


async def unlink_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /unlink command.

    Unlinks the user's Telegram account from Oracle account (security feature).

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/unlink command from user {telegram_user_id}")

        # Check if linked
        is_linked = await check_user_linked(telegram_user_id)

        if not is_linked:
            await update.message.reply_text(
                "Contul tau nu este linkuit.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Create confirmation keyboard
        keyboard = [
            [
                InlineKeyboardButton("Da, deconecteaza", callback_data="unlink_confirm"),
                InlineKeyboardButton("Anuleaza", callback_data="unlink_cancel")
            ]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)

        await update.message.reply_text(
            "**Confirmare Deconectare**\n\n"
            "Esti sigur ca vrei sa deconectezi contul?\n\n"
            "Accesul la date va fi oprit. Poti reconecta oricand cu un cod nou.\n\n"
            "Confirma:",
            reply_markup=reply_markup,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in unlink_command: {e}", exc_info=True)
        await update.message.reply_text(
            "A aparut o eroare."
        )


async def selectcompany_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /selectcompany [search_term] command.

    Permite căutare și selectare companie cu PAGINARE (identic cu butoanele).

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/selectcompany command from user {telegram_user_id}")

        # Check if user is linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get search term from command arguments (optional)
        search_term = " ".join(context.args) if context.args else ""

        # ✅ MODIFICARE: Folosim funcția comună cu paginare
        await _handle_selectcompany_view(
            query_or_update=update,
            telegram_user_id=telegram_user_id,
            jwt_token=jwt_token,
            is_callback=False,
            page=0,
            search_term=search_term
        )

    except Exception as e:
        logger.error(f"Error in selectcompany_command: {e}", exc_info=True)
        await update.message.reply_text("A aparut o eroare. Te rog incearca din nou.")


async def dashboard_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /dashboard command - shows financial dashboard."""
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/dashboard command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # ✅ MODIFICARE: Folosim funcția comună
        await _handle_sold_view(
            query_or_update=update,
            telegram_user_id=telegram_user_id,
            company=company,
            jwt_token=jwt_token,
            is_callback=False
        )

    except Exception as e:
        logger.error(f"Error in dashboard_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea dashboard-ului.")


async def sold_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /sold command - alias for /dashboard."""
    await dashboard_command(update, context)


async def facturi_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /facturi [filtru] command - shows invoices list."""
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/facturi command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont nelinkuit**\n\nFoloseste /start.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return

        # Parse filters from args (optional: "neplatite", "platite", etc.)
        filters = {}
        if context.args:
            status_arg = context.args[0].lower()
            if status_arg in ['neplatite', 'unpaid']:
                filters['status'] = 'unpaid'
            elif status_arg in ['platite', 'paid']:
                filters['status'] = 'paid'

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Call API
        client = get_backend_client()
        async with client:
            invoices = await client.search_invoices(
                company_id=company['id'],
                jwt_token=jwt_token,
                filters=filters if filters else None
            )

        # Format response
        from backend.modules.telegram.bot.formatters import format_invoices_response
        response = format_invoices_response(invoices, company['name'])

        # FAZA 3: Add action buttons
        from backend.modules.telegram.bot.menus import create_action_buttons
        keyboard = create_action_buttons("facturi", show_export=True)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in facturi_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea facturilor.")


async def trezorerie_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /trezorerie command - shows total treasury (casa + banca).

    Afișează sold total trezorerie cu defalcare și butoane pentru detalii.
    """
    try:
        telegram_user_id = update.effective_user.id

        logger.info(f"/trezorerie command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # ✅ MODIFICARE: Folosim treasury_breakdown_split ca în Casa/Banca
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not treasury_data:
            await update.message.reply_text("Eroare la incarcarea trezoreriei.")
            return

        # Extract cache metadata
        cache_hit = treasury_data.get('cache_hit', False)
        response_time_ms = treasury_data.get('response_time_ms', 0)
        cache_source = treasury_data.get('cache_source', None)

        # Format combined response (casa + banca) - rotunjit la leu (0 zecimale)
        casa_total = round(treasury_data['casa']['total'])
        banca_total = round(treasury_data['banca']['total'])
        total_treasury = casa_total + banca_total

        content = f"**Sold Total:** {total_treasury:,} RON\n\n"
        content += f"**Defalcare:**\n"
        content += f"  - Casa: {casa_total:,} RON\n"
        content += f"  - Banca: {banca_total:,} RON\n\n"
        content += "Foloseste butoanele pentru detalii:"

        # Apply company header formatting
        from backend.modules.telegram.bot.menus import format_response_with_company
        text = format_response_with_company(content, company['name'])

        # Add performance footer
        if response_time_ms > 0:
            from backend.modules.telegram.bot.formatters import add_performance_footer
            text = add_performance_footer(text, cache_hit, response_time_ms, cache_source)

        # Add buttons to view details
        from telegram import InlineKeyboardButton, InlineKeyboardMarkup
        keyboard = InlineKeyboardMarkup([
            [
                InlineKeyboardButton("Detalii Casa", callback_data="menu:casa"),
                InlineKeyboardButton("Detalii Banca", callback_data="menu:banca")
            ],
            [
                InlineKeyboardButton("Meniu Principal", callback_data="action:menu")
            ]
        ])

        await update.message.reply_text(
            text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in trezorerie_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea trezoreriei.")


async def menu_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /menu command - shows main menu with interactive buttons.

    Displays the main menu with 6 financial options organized in a 2-column layout.
    Requires user to be linked and have an active company selected.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/menu command from user {telegram_user_id}")

        # Check if user is linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        session = await session_manager.get_or_create_session(telegram_user_id)
        company = session.get_active_company()

        # Get company data for menu
        company_name = company['name'] if company else None
        company_cui = company.get('cui') if company else None

        # Get cache status for user
        cache_enabled = None
        try:
            from backend.modules.telegram.api.client import get_backend_client
            client = get_backend_client()
            async with client:
                cache_stats = await client.get_cache_stats(jwt_token=auth_data['jwt_token'])
                cache_enabled = cache_stats.get('user_enabled', True)
        except Exception as e:
            logger.warning(f"Could not get cache status: {e}")

        # Create main menu (user is authenticated if they passed the is_linked check)
        from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
        keyboard = create_main_menu(company_name, company_cui, is_authenticated=True, cache_enabled=cache_enabled)
        menu_text = get_menu_message(company_name, company_cui)

        await update.message.reply_text(
            menu_text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in menu_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la afisarea meniului.")


async def trezorerie_casa_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /trezorerie_casa command - shows cash treasury data.

    Displays treasury data for cash accounts only (Casa).

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/trezorerie_casa command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get treasury breakdown split
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not treasury_data:
            await update.message.reply_text("Eroare la incarcarea trezoreriei cash.")
            return

        # Format response
        from backend.modules.telegram.bot.formatters import format_treasury_casa_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_treasury_casa_response(treasury_data['casa'])
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
            cache_hit = treasury_data['cache_hit']
            response_time_ms = treasury_data['response_time_ms']
            cache_source = treasury_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("casa", show_export=True)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in trezorerie_casa_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea trezoreriei cash.")


async def trezorerie_banca_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /trezorerie_banca command - shows bank treasury data.

    Displays treasury data for bank accounts only (Banca).

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/trezorerie_banca command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get treasury breakdown split
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not treasury_data:
            await update.message.reply_text("Eroare la incarcarea trezoreriei bancare.")
            return

        # Format response
        from backend.modules.telegram.bot.formatters import format_treasury_banca_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_treasury_banca_response(treasury_data['banca'])
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
            cache_hit = treasury_data['cache_hit']
            response_time_ms = treasury_data['response_time_ms']
            cache_source = treasury_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("banca", show_export=True)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in trezorerie_banca_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea trezoreriei bancare.")


async def clienti_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /clienti command - shows clients balance with maturity breakdown.

    Displays total clients balance, in-term and overdue amounts, and list of clients
    with interactive buttons to view details.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/clienti command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get clients with maturity data
        from backend.modules.telegram.bot.helpers import get_clients_with_maturity
        clients_data = await get_clients_with_maturity(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not clients_data:
            await update.message.reply_text("Eroare la incarcarea datelor clienti.")
            return

        # Extract cache metadata
        cache_hit = clients_data.get('cache_hit', False)
        response_time_ms = clients_data.get('response_time_ms', 0)
        cache_source = clients_data.get('cache_source', None)

        # Format response
        from backend.modules.telegram.bot.formatters import format_clients_balance_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_client_list_keyboard, format_response_with_company

        content = format_clients_balance_response(
            clients_data['clients'],
            clients_data['maturity']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer
        if response_time_ms > 0:
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_client_list_keyboard(clients_data['clients'], page=0)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in clienti_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea datelor clienti.")


async def furnizori_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /furnizori command - shows suppliers balance with maturity breakdown.

    Displays total suppliers balance, in-term and overdue amounts, and list of suppliers
    with interactive buttons to view details.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/furnizori command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get suppliers with maturity data
        from backend.modules.telegram.bot.helpers import get_suppliers_with_maturity
        suppliers_data = await get_suppliers_with_maturity(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not suppliers_data:
            await update.message.reply_text("Eroare la incarcarea datelor furnizori.")
            return

        # Extract cache metadata
        cache_hit = suppliers_data.get('cache_hit', False)
        response_time_ms = suppliers_data.get('response_time_ms', 0)
        cache_source = suppliers_data.get('cache_source', None)

        # Format response
        from backend.modules.telegram.bot.formatters import format_suppliers_balance_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_supplier_list_keyboard, format_response_with_company

        content = format_suppliers_balance_response(
            suppliers_data['suppliers'],
            suppliers_data['maturity']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer
        if response_time_ms > 0:
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_supplier_list_keyboard(suppliers_data['suppliers'], page=0)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in furnizori_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea datelor furnizori.")


async def evolutie_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle /evolutie command - shows cash flow evolution (collections/payments).

    Displays performance data and monthly cash flow trends for collections and payments.

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user_id = update.effective_user.id
        logger.info(f"/evolutie command from user {telegram_user_id}")

        # Check linked
        is_linked = await check_user_linked(telegram_user_id)
        if not is_linked:
            await update.message.reply_text(
                "**Cont neconectat**\n\nFoloseste /start",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        # Get active company
        session_manager = get_session_manager()
        from backend.modules.telegram.bot.helpers import get_active_company_or_prompt
        company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)

        if not company:
            return  # Prompt already sent

        # Get auth data
        auth_data = await get_user_auth_data(telegram_user_id)
        jwt_token = auth_data['jwt_token']

        # Get cash flow evolution data
        from backend.modules.telegram.bot.helpers import get_cashflow_evolution_data
        evolution_data = await get_cashflow_evolution_data(
            company_id=company['id'],
            jwt_token=jwt_token
        )

        if not evolution_data:
            await update.message.reply_text("Eroare la incarcarea datelor evolutie.")
            return

        # Format response
        from backend.modules.telegram.bot.formatters import format_cashflow_evolution_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_cashflow_evolution_response(
            evolution_data['performance'],
            evolution_data['monthly']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in evolution_data and 'response_time_ms' in evolution_data:
            cache_hit = evolution_data['cache_hit']
            response_time_ms = evolution_data['response_time_ms']
            cache_source = evolution_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("evolutie", show_export=False, show_refresh=False)

        await update.message.reply_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    except Exception as e:
        logger.error(f"Error in evolutie_command: {e}", exc_info=True)
        await update.message.reply_text("Eroare la incarcarea datelor evolutie.")


# ============================================================================
# TEXT MESSAGE HANDLERS
# ============================================================================

async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle regular text messages.

    Automatically detects and processes linking codes when user sends
    a text that matches the code format (8 alphanumeric characters).

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        telegram_user = update.effective_user
        telegram_user_id = telegram_user.id
        text = update.message.text.strip().upper()

        logger.info(f"Text message from user {telegram_user_id}: {text}")

        # Check if user is already linked
        is_linked = await check_user_linked(telegram_user_id)

        if is_linked:
            # User is already linked - ignore text messages
            # (could add natural language processing here in the future)
            return

        # User is NOT linked - check if text looks like a linking code
        # Linking codes are exactly 8 alphanumeric characters
        if len(text) == 8 and text.isalnum():
            logger.info(f"Detected potential linking code: {text} from user {telegram_user_id}")

            # ȘTERGE mesajul utilizatorului cu codul (chat curat)
            try:
                await update.message.delete()
            except Exception as e:
                logger.warning(f"Could not delete code message: {e}")

            # Check dacă există mesaj de editat din "Login din Web App"
            web_login_msg_id = context.user_data.get('web_login_message_id')

            if web_login_msg_id:
                # EDITEAZĂ mesajul existent cu instrucțiunile
                try:
                    await context.bot.edit_message_text(
                        chat_id=update.effective_chat.id,
                        message_id=web_login_msg_id,
                        text="Conectare cont...",
                        parse_mode=ParseMode.MARKDOWN
                    )
                except Exception as e:
                    logger.warning(f"Could not edit web_login message: {e}")
                    # Fallback: creează mesaj nou
                    web_login_msg_id = None

            # Dacă nu există mesaj de editat, creează unul nou
            if not web_login_msg_id:
                linking_msg = await update.effective_chat.send_message(
                    "Conectare cont...",
                    parse_mode=ParseMode.MARKDOWN
                )
                web_login_msg_id = linking_msg.message_id

            # Attempt linking
            result = await link_telegram_account(telegram_user, text)

            if result:
                # Success!
                username = result['username']
                # Show main menu with buttons for newly linked user
                session_manager = get_session_manager()
                session = await session_manager.get_or_create_session(telegram_user_id)
                company = session.get_active_company()
                company_name = company['name'] if company else None
                company_cui = company.get('cui') if company else None

                from backend.modules.telegram.bot.menus import create_main_menu, pad_message_for_wide_buttons
                keyboard = create_main_menu(company_name, company_cui, is_authenticated=True)

                # Create menu text
                if company_name:
                    menu_text = f"{company_name}"
                else:
                    menu_text = "Selectează o companie pentru a continua"

                menu_message = pad_message_for_wide_buttons(menu_text)

                # EDIT the same message to show menu (no new messages!)
                await context.bot.edit_message_text(
                    chat_id=update.effective_chat.id,
                    message_id=web_login_msg_id,
                    text=menu_message,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )

                logger.info(f"User {telegram_user_id} successfully linked to {username} via direct code input")
            else:
                # Failed linking - EDIT the same message to show error
                await context.bot.edit_message_text(
                    chat_id=update.effective_chat.id,
                    message_id=web_login_msg_id,
                    text="Cod invalid sau expirat\n\n"
                         "Generează un cod nou din aplicația web și trimite-l direct.\n\n"
                         "Codul expiră în 15 minute.",
                    parse_mode=ParseMode.MARKDOWN
                )

                logger.warning(f"Failed to link user {telegram_user_id} with direct code: {text}")
        else:
            # Text doesn't look like a linking code
            # Show helpful message
            keyboard = InlineKeyboardMarkup([
                [InlineKeyboardButton("Cum obtin codul de link?", callback_data="login_help")],
                [InlineKeyboardButton("Am deja cod - Linkez contul", callback_data="login_prompt")]
            ])

            await update.message.reply_text(
                "**Salut**\n\n"
                "Pentru a folosi bot-ul, conecteaza contul tau ROA2WEB.\n\n"
                "Codul are exact 8 caractere (exemplu: ABC12XYZ)\n\n"
                "Alege o optiune:",
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

    except Exception as e:
        logger.error(f"Error in handle_text_message: {e}", exc_info=True)
        await update.message.reply_text(
            "A aparut o eroare. Te rog incearca din nou."
        )


# ============================================================================
# CALLBACK QUERY HANDLERS (for inline buttons)
# ============================================================================

async def handle_menu_callback(query, telegram_user_id: int, callback_data: str):
    """
    Handle main menu button clicks.

    Callback format: menu:{action}
    Actions: sold, casa, banca, clienti, furnizori, evolutie, select_company

    Args:
        query: CallbackQuery object
        telegram_user_id: Telegram user ID
        callback_data: Callback data string
    """
    action = callback_data.split(":")[1]

    # Get auth data
    auth_data = await get_user_auth_data(telegram_user_id)

    # If user is not authenticated and trying to access financial data, show auth required message
    if auth_data is None and action != "select_company":
        from backend.modules.telegram.bot.menus import create_main_menu, pad_message_for_wide_buttons
        keyboard = create_main_menu(company_name=None, company_cui=None, is_authenticated=False)
        menu_text = pad_message_for_wide_buttons(
            "⚠️ **Autentificare necesară**\n\n"
            "Pentru a accesa date financiare,\n"
            "apasă **Login** și urmează instrucțiunile."
        )

        await query.edit_message_text(
            menu_text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )
        return

    # If action is select_company and user is not authenticated, allow it (will show empty list or error)
    if action == "select_company" and auth_data is None:
        await query.answer("Pentru a vedea companiile, trebuie să te autentifici mai întâi.", show_alert=True)
        return

    jwt_token = auth_data['jwt_token']

    # Get active company
    session_manager = get_session_manager()
    session = await session_manager.get_or_create_session(telegram_user_id)
    company = session.get_active_company()

    if not company and action != "select_company":
        # Get companies and show selection directly
        client = get_backend_client()
        async with client:
            companies = await client.get_user_companies(jwt_token=jwt_token)

        if not companies:
            await query.edit_message_text(
                "Nu ai acces la nicio companie.\n"
                "Contacteaza administratorul.",
                parse_mode=ParseMode.MARKDOWN
            )
            return

        from backend.modules.telegram.bot.helpers import create_company_selection_keyboard_paginated
        keyboard = create_company_selection_keyboard_paginated(companies, page=0)

        await query.edit_message_text(
            f"**Selecteaza mai intai o companie**\n\n"
            f"Companiile tale ({len(companies)}):",
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )
        return

    # Route to appropriate handler
    if action == "sold":
        # ✅ MODIFICARE: Folosim funcția comună
        await _handle_sold_view(
            query_or_update=query,
            telegram_user_id=telegram_user_id,
            company=company,
            jwt_token=jwt_token,
            is_callback=True
        )

    elif action == "trezorerie":
        # Trezorerie unified (Casa + Banca combined)
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_treasury_combined_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_treasury_combined_response(treasury_data)
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
            cache_hit = treasury_data['cache_hit']
            response_time_ms = treasury_data['response_time_ms']
            cache_source = treasury_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("trezorerie", show_export=False, show_refresh=False)

        try:
            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        except Exception as e:
            # Ignore "Message is not modified" error
            if "Message is not modified" not in str(e):
                raise

    elif action == "casa":
        # Trezorerie casa
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_treasury_casa_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_treasury_casa_response(treasury_data['casa'])
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
            cache_hit = treasury_data['cache_hit']
            response_time_ms = treasury_data['response_time_ms']
            cache_source = treasury_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("casa", show_export=False, show_refresh=False)

        try:
            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        except Exception as e:
            # Ignore "Message is not modified" error
            if "Message is not modified" not in str(e):
                raise

    elif action == "banca":
        # Trezorerie banca
        from backend.modules.telegram.bot.helpers import get_treasury_breakdown_split
        treasury_data = await get_treasury_breakdown_split(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_treasury_banca_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_treasury_banca_response(treasury_data['banca'])
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
            cache_hit = treasury_data['cache_hit']
            response_time_ms = treasury_data['response_time_ms']
            cache_source = treasury_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("banca", show_export=False, show_refresh=False)

        try:
            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        except Exception as e:
            # Ignore "Message is not modified" error
            if "Message is not modified" not in str(e):
                raise

    elif action == "clienti":
        # Sold clienți + listă cu paginare
        from backend.modules.telegram.bot.helpers import get_clients_with_maturity
        clients_data = await get_clients_with_maturity(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_clients_balance_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_client_list_keyboard, format_response_with_company

        content = format_clients_balance_response(
            clients_data['clients'],
            clients_data['maturity']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in clients_data and 'response_time_ms' in clients_data:
            cache_hit = clients_data['cache_hit']
            response_time_ms = clients_data['response_time_ms']
            cache_source = clients_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_client_list_keyboard(clients_data['clients'], page=0)

        await query.edit_message_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif action == "furnizori":
        # Sold furnizori + listă cu paginare
        from backend.modules.telegram.bot.helpers import get_suppliers_with_maturity
        suppliers_data = await get_suppliers_with_maturity(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_suppliers_balance_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_supplier_list_keyboard, format_response_with_company

        content = format_suppliers_balance_response(
            suppliers_data['suppliers'],
            suppliers_data['maturity']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in suppliers_data and 'response_time_ms' in suppliers_data:
            cache_hit = suppliers_data['cache_hit']
            response_time_ms = suppliers_data['response_time_ms']
            cache_source = suppliers_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_supplier_list_keyboard(suppliers_data['suppliers'], page=0)

        await query.edit_message_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif action == "evolutie":
        # Evoluție cash flow
        from backend.modules.telegram.bot.helpers import get_cashflow_evolution_data
        evolution_data = await get_cashflow_evolution_data(company['id'], jwt_token)

        from backend.modules.telegram.bot.formatters import format_cashflow_evolution_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_cashflow_evolution_response(
            evolution_data['performance'],
            evolution_data['monthly']
        )
        response = format_response_with_company(content, company['name'])

        # Add performance footer if cache metadata is available
        if 'cache_hit' in evolution_data and 'response_time_ms' in evolution_data:
            cache_hit = evolution_data['cache_hit']
            response_time_ms = evolution_data['response_time_ms']
            cache_source = evolution_data.get('cache_source', None)
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)

        keyboard = create_action_buttons("evolutie", show_export=False, show_refresh=False)

        await query.edit_message_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif action == "togglecache":
        # Toggle cache pentru user
        try:
            client = get_backend_client()
            async with client:
                cache_stats = await client.get_cache_stats(jwt_token=jwt_token)
                user_enabled = cache_stats.get('user_enabled', True)

            # Create toggle buttons
            from telegram import InlineKeyboardButton, InlineKeyboardMarkup
            keyboard = [
                [
                    InlineKeyboardButton(
                        "✅ Activează" if not user_enabled else "❌ Dezactivează",
                        callback_data=f"cache_toggle:{'on' if not user_enabled else 'off'}"
                    )
                ],
                [InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
            ]
            reply_markup = InlineKeyboardMarkup(keyboard)

            status = "ACTIVAT" if user_enabled else "DEZACTIVAT"
            message = f"**Cache Status**\n\nCurent: {status}\n\n"

            if user_enabled:
                message += "Vrei să dezactivezi cache-ul temporar?\nFolosește pentru teste de performanță."
            else:
                message += "Cache-ul este dezactivat.\nToate queries merg direct la Oracle."

            await query.edit_message_text(
                message,
                reply_markup=reply_markup,
                parse_mode=ParseMode.MARKDOWN
            )
        except Exception as e:
            logger.error(f"Toggle cache menu error: {e}", exc_info=True)
            await query.answer("Eroare la obținerea status cache.", show_alert=True)

    elif action == "clearcache":
        # Clear cache
        try:
            # Create inline keyboard
            from telegram import InlineKeyboardButton, InlineKeyboardMarkup
            keyboard = [
                [
                    InlineKeyboardButton("Toate companiile", callback_data="cache_clear:all"),
                    InlineKeyboardButton("Doar compania mea", callback_data="cache_clear:current")
                ],
                [InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
            ]
            reply_markup = InlineKeyboardMarkup(keyboard)

            message = "**🔄 Invalidare Cache**\n\n"
            if company:
                message += f"Compania curentă: {company['name']}\n\n"
            message += "Alege scope:"

            await query.edit_message_text(
                message,
                reply_markup=reply_markup,
                parse_mode=ParseMode.MARKDOWN
            )
        except Exception as e:
            logger.error(f"Clear cache menu error: {e}", exc_info=True)
            await query.answer("Eroare la afișarea opțiuni cache.", show_alert=True)

    elif action == "select_company":
        # ✅ MODIFICARE: Folosim funcția comună
        await _handle_selectcompany_view(
            query_or_update=query,
            telegram_user_id=telegram_user_id,
            jwt_token=jwt_token,
            is_callback=True,
            page=0,
            search_term=""
        )


async def handle_action_callback(query, telegram_user_id: int, callback_data: str):
    """
    Handle action button clicks (Refresh, Export, Menu, Help, Login, Logout).

    Callback format: action:{type}:{view}
    Types: refresh, export, menu, help, login, logout

    Args:
        query: CallbackQuery object
        telegram_user_id: Telegram user ID
        callback_data: Callback data string
    """
    parts = callback_data.split(":")
    action_type = parts[1]

    if action_type == "menu":
        # Back to main menu
        session_manager = get_session_manager()
        session = await session_manager.get_or_create_session(telegram_user_id)
        company = session.get_active_company()

        # Check if user is authenticated
        auth_data = await get_user_auth_data(telegram_user_id)
        is_authenticated = auth_data is not None

        # Get cache status for user
        cache_enabled = None
        if is_authenticated:
            try:
                from backend.modules.telegram.api.client import get_backend_client
                client = get_backend_client()
                async with client:
                    cache_stats = await client.get_cache_stats(jwt_token=auth_data['jwt_token'])
                    cache_enabled = cache_stats.get('user_enabled', True)
            except Exception as e:
                logger.warning(f"Could not get cache status: {e}")

        from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
        company_name = company['name'] if company else None
        company_cui = company.get('cui') if company else None
        keyboard = create_main_menu(company_name, company_cui, is_authenticated, cache_enabled)
        menu_text = get_menu_message(company_name, company_cui)

        await query.edit_message_text(
            menu_text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif action_type == "refresh":
        # Refresh current view
        view = parts[2] if len(parts) > 2 else "sold"

        # Check if it's a detail view (client_detail:name or supplier_detail:name)
        if view.startswith("client_detail:"):
            entity_name = view.split(":", 1)[1]  # Extract entity name
            # Limit name to 40 chars for Telegram callback_data limit (64 bytes)
            safe_name = entity_name[:40] if len(entity_name) > 40 else entity_name
            await handle_details_callback(query, telegram_user_id, f"details:client:{safe_name}:0")
        elif view.startswith("supplier_detail:"):
            entity_name = view.split(":", 1)[1]  # Extract entity name
            # Limit name to 40 chars for Telegram callback_data limit (64 bytes)
            safe_name = entity_name[:40] if len(entity_name) > 40 else entity_name
            await handle_details_callback(query, telegram_user_id, f"details:supplier:{safe_name}:0")
        else:
            # Regular menu view refresh
            await handle_menu_callback(query, telegram_user_id, f"menu:{view}")

    elif action_type == "export":
        # Export functionality (placeholder for now)
        await query.answer("Functia de export va fi disponibila in curand", show_alert=True)

    elif action_type == "help":
        # Show help message above menu (edit current message)
        from backend.modules.telegram.bot.menus import pad_message_for_wide_buttons, create_main_menu

        # Get auth status and company info
        session_manager = get_session_manager()
        session = await session_manager.get_or_create_session(telegram_user_id)
        company = session.get_active_company()

        auth_data = await get_user_auth_data(telegram_user_id)
        is_authenticated = auth_data is not None

        company_name = company['name'] if company else None
        company_cui = company.get('cui') if company else None

        keyboard = create_main_menu(company_name, company_cui, is_authenticated)

        help_text = pad_message_for_wide_buttons(
            "**Ghid Rapid**\n\n"
            "**Selectare Companie** - Alege compania activă\n\n"
            "**Sold Companie** - Dashboard financiar complet\n"
            "**Trezorerie Casa** - Situație conturi cash\n"
            "**Trezorerie Banca** - Situație conturi bancare\n"
            "**Sold Clienti** - Clienți + facturi neplătite\n"
            "**Sold Furnizori** - Furnizori + facturi\n"
            "**Evolutie Incasari** - Trend lunar încasări\n\n"
            "**Logout** - Deconectează contul\n\n"
            "_Toate datele sunt în timp real din Oracle._"
        )

        await query.edit_message_text(
            help_text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif action_type == "logout":
        # Show logout confirmation
        from backend.modules.telegram.bot.menus import pad_message_for_wide_buttons
        confirmation_text = pad_message_for_wide_buttons(
            "**Confirmare Deconectare**\n\n"
            "Ești sigur că vrei să deconectezi contul?\n\n"
            "Accesul la date va fi oprit.\n"
            "Poți reconecta oricând cu un cod nou."
        )

        keyboard = InlineKeyboardMarkup([
            [
                InlineKeyboardButton("Da, deconectează", callback_data="logout_confirm"),
                InlineKeyboardButton("Anulează", callback_data="logout_cancel")
            ]
        ])

        await query.edit_message_text(
            confirmation_text,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    # NOTE: action:login is handled by email_login_handler ConversationHandler
    # See app/bot/email_handlers.py for the complete email authentication flow


async def handle_details_callback(query, telegram_user_id: int, callback_data: str):
    """
    Handle client/supplier detail clicks.

    Callback format: details:{type}:{name}:{page}
    Types: client, supplier

    Args:
        query: CallbackQuery object
        telegram_user_id: Telegram user ID
        callback_data: Callback data string
    """
    parts = callback_data.split(":")
    detail_type = parts[1]  # client or supplier
    entity_name = parts[2]  # client/supplier name
    page = int(parts[3]) if len(parts) > 3 else 0  # invoice page number

    # Get auth data and company
    auth_data = await get_user_auth_data(telegram_user_id)
    jwt_token = auth_data['jwt_token']

    session_manager = get_session_manager()
    session = await session_manager.get_or_create_session(telegram_user_id)
    company = session.get_active_company()

    if detail_type == "client":
        # Get client details (from clients list)
        # entity_name might be truncated to 40 chars, so search by startswith
        from backend.modules.telegram.bot.helpers import get_clients_with_maturity
        clients_data = await get_clients_with_maturity(company['id'], jwt_token)

        # Find client by full or partial name match
        client = next((c for c in clients_data['clients'] if c['name'].startswith(entity_name)), None)

        if not client:
            await query.answer("Client negăsit", show_alert=True)
            return

        # Use FULL client name for invoice search (not truncated)
        full_client_name = client['name']

        # Get client invoices by FULL name
        from backend.modules.telegram.bot.helpers import get_client_invoices
        invoices = await get_client_invoices(company['id'], full_client_name, jwt_token)

        # Format response
        from backend.modules.telegram.bot.formatters import format_client_detail_response
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_client_detail_response(client, invoices)
        response = format_response_with_company(content, company['name'])

        # Use truncated name for callback_data (to stay within 64 byte limit)
        safe_name = entity_name[:40] if len(entity_name) > 40 else entity_name
        keyboard = create_action_buttons(f"client_detail:{safe_name}", show_export=False, show_back=True, show_refresh=False)

        await query.edit_message_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )

    elif detail_type == "supplier":
        # Get supplier details (from suppliers list)
        # entity_name might be truncated to 40 chars, so search by startswith
        from backend.modules.telegram.bot.helpers import get_suppliers_with_maturity
        suppliers_data = await get_suppliers_with_maturity(company['id'], jwt_token)

        # Find supplier by full or partial name match
        supplier = next((s for s in suppliers_data['suppliers'] if s['name'].startswith(entity_name)), None)

        if not supplier:
            await query.answer("Furnizor negăsit", show_alert=True)
            return

        # Use FULL supplier name for invoice search (not truncated)
        full_supplier_name = supplier['name']

        # Get supplier invoices by FULL name
        from backend.modules.telegram.bot.helpers import get_supplier_invoices
        invoices = await get_supplier_invoices(company['id'], full_supplier_name, jwt_token)

        # Format response
        from backend.modules.telegram.bot.formatters import format_supplier_detail_response
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        content = format_supplier_detail_response(supplier, invoices)
        response = format_response_with_company(content, company['name'])

        # Use truncated name for callback_data (to stay within 64 byte limit)
        safe_name = entity_name[:40] if len(entity_name) > 40 else entity_name
        keyboard = create_action_buttons(f"supplier_detail:{safe_name}", show_export=False, show_back=True, show_refresh=False)

        await query.edit_message_text(
            response,
            reply_markup=keyboard,
            parse_mode=ParseMode.MARKDOWN
        )


async def handle_invoice_callback(query, telegram_user_id: int, callback_data: str):
    """
    Handle invoice detail clicks.

    Callback format: invoice:{partner_type}:{id}

    Args:
        query: CallbackQuery object
        telegram_user_id: Telegram user ID
        callback_data: Callback data string
    """
    parts = callback_data.split(":")
    partner_type = parts[1]  # CLIENTI or FURNIZORI
    invoice_id = int(parts[2])

    # Get invoice details from API (placeholder for now)
    await query.answer("Detalii factura (in dezvoltare)", show_alert=True)


async def handle_navigation_back(query, telegram_user_id: int, callback_data: str):
    """
    Handle back navigation.

    Callback format: nav:back:{location}
    Locations: menu, clienti, furnizori

    Args:
        query: CallbackQuery object
        telegram_user_id: Telegram user ID
        callback_data: Callback data string
    """
    location = callback_data.split(":")[2]

    if location == "menu":
        # Back to main menu
        await handle_action_callback(query, telegram_user_id, "action:menu")

    elif location == "clienti":
        # Back to clients list
        await handle_menu_callback(query, telegram_user_id, "menu:clienti")

    elif location == "furnizori":
        # Back to suppliers list
        await handle_menu_callback(query, telegram_user_id, "menu:furnizori")


async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle inline button callbacks.

    Callback data formats:
    - login_help - Show help on how to get link code
    - login_prompt - Prompt user to enter link code
    - login_back - Back to welcome message
    - menu:{action} - Main menu buttons
    - action:{type}:{view} - Action buttons (refresh, export, menu)
    - details:{type}:{id} - Client/Supplier details
    - invoice:{partner_type}:{id} - Invoice details
    - nav:back:{location} - Navigation back
    - select_company:{id} - Company selection (existing)
    - unlink_confirm/unlink_cancel - Unlink confirmation (existing)

    Args:
        update: Telegram update object
        context: Telegram context
    """
    try:
        query = update.callback_query
        callback_data = query.data

        # ========== IGNORE CALLBACKS HANDLED BY CONVERSATION HANDLER ==========
        # These callbacks are managed by email_login_handler ConversationHandler
        # Return immediately without answering to let ConversationHandler process them
        conversation_patterns = [
            'action:login',      # Login button from menu
            'email_login',       # Email login button
            'web_login_info',    # Web app login info button
            'cancel',            # Cancel button
        ]

        # Check exact matches
        if callback_data in conversation_patterns:
            logger.info(f"[BUTTON_CALLBACK] Ignoring {callback_data} - handled by ConversationHandler")
            return

        # Check prefix matches (e.g., resend:email@example.com)
        if callback_data.startswith('resend:'):
            logger.info(f"[BUTTON_CALLBACK] Ignoring {callback_data} - handled by ConversationHandler")
            return

        # ========== PROCESS ALL OTHER CALLBACKS ==========
        await query.answer()

        telegram_user_id = update.effective_user.id

        logger.info(f"Button callback: {callback_data} from user {telegram_user_id}")

        # ========== EXISTING CALLBACKS (preserve) ==========

        # Handle pagination for company selection
        if callback_data.startswith("select_company_page:"):
            # Extract page number
            page = int(callback_data.split(":")[1])

            # Get companies
            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            client = get_backend_client()
            async with client:
                companies = await client.get_user_companies(jwt_token=jwt_token)

            # Create paginated keyboard for requested page
            from backend.modules.telegram.bot.helpers import create_company_selection_keyboard_paginated
            keyboard = create_company_selection_keyboard_paginated(companies, page=page)

            await query.edit_message_text(
                f"**Selecteaza Compania**\n\n"
                f"Companiile tale ({len(companies)}):",
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        elif callback_data.startswith("select_company:"):
            # Handle company selection
            company_id = int(callback_data.split(":")[1])

            # Get company details
            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            client = get_backend_client()
            async with client:
                companies = await client.get_user_companies(jwt_token=jwt_token)

            # Find selected company
            selected = next(
                (c for c in companies if c.get('id_firma', c.get('id')) == company_id),
                None
            )

            if selected:
                # Set active company in session
                session_manager = get_session_manager()
                session = await session_manager.get_or_create_session(telegram_user_id)

                # Extract company data with backwards compatibility
                company_name = selected.get('name', selected.get('nume_firma', 'N/A'))
                company_cui = selected.get('fiscal_code', selected.get('cui'))

                session.set_active_company(
                    company_id=company_id,
                    company_name=company_name,
                    company_cui=company_cui
                )
                await session_manager.save_session(telegram_user_id)

                # Show main menu directly (no confirmation message)
                from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
                keyboard = create_main_menu(
                    company_name=company_name,
                    company_cui=company_cui
                )
                menu_text = get_menu_message(company_name, company_cui)

                await query.edit_message_text(
                    menu_text,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )
            else:
                await query.edit_message_text(
                    "Companie negasita sau nu ai acces la ea."
                )

        # ========== LOGOUT CALLBACKS ==========

        elif callback_data == "logout_confirm":
            # Logout user (same as unlink but shows menu after)
            from backend.modules.telegram.auth.linking import unlink_user

            success = await unlink_user(telegram_user_id)

            if success:
                # Clear session too
                session_manager = get_session_manager()
                await session_manager.delete_session(telegram_user_id)

                # Show login menu (non-authenticated)
                from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message, pad_message_for_wide_buttons
                keyboard = create_main_menu(company_name=None, company_cui=None, is_authenticated=False)
                menu_text = pad_message_for_wide_buttons(
                    "**Deconectat cu succes**\n\n"
                    "Contul tău a fost deconectat.\n\n"
                    "Pentru a te reconecta, apasă **Login**."
                )

                await query.edit_message_text(
                    menu_text,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )
            else:
                await query.edit_message_text(
                    "A apărut o eroare la deconectare.\n"
                    "Te rog încearcă din nou."
                )

        elif callback_data == "logout_cancel":
            # Cancel logout - return to main menu
            session_manager = get_session_manager()
            session = await session_manager.get_or_create_session(telegram_user_id)
            company = session.get_active_company()

            # Check auth
            auth_data = await get_user_auth_data(telegram_user_id)
            is_authenticated = auth_data is not None

            from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
            company_name = company['name'] if company else None
            company_cui = company.get('cui') if company else None
            keyboard = create_main_menu(company_name, company_cui, is_authenticated)
            menu_text = get_menu_message(company_name, company_cui)

            await query.edit_message_text(
                menu_text,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        # ========== UNLINK CALLBACKS (LEGACY) ==========

        elif callback_data == "unlink_confirm":
            # Unlink user
            from backend.modules.telegram.auth.linking import unlink_user

            success = await unlink_user(telegram_user_id)

            if success:
                # Clear session too
                session_manager = get_session_manager()
                await session_manager.delete_session(telegram_user_id)

                await query.edit_message_text(
                    "**Cont deconectat cu succes**\n\n"
                    "Datele tale au fost șterse din sistem.\n\n"
                    "Pentru a te reconecta, folosește `/start CODUL_TAU`",
                    parse_mode=ParseMode.MARKDOWN
                )
            else:
                await query.edit_message_text(
                    "A aparut o eroare la deconectare.\n"
                    "Te rog incearca din nou."
                )

        elif callback_data == "unlink_cancel":
            await query.edit_message_text(
                "Deconectare anulata.\n\n"
                "Contul tau ramane linkuit."
            )

        # ========== LOGIN CALLBACKS ==========

        elif callback_data == "login_help":
            # Show detailed help on how to get link code
            await query.edit_message_text(
                "**Cum obțin codul de link?**\n\n"
                "1. Loghează-te în aplicația web ROA2WEB\n"
                "2. Mergi la: Setări → Telegram Linking\n"
                "3. Apasă **Generează Cod**\n"
                "4. Vei primi un cod din 8 caractere (ex: ABC12XYZ)\n"
                "5. Trimite-mi comanda: `/start CODUL_TAU`\n\n"
                "**Important:** Codul expiră în 15 minute.",
                reply_markup=InlineKeyboardMarkup([
                    [InlineKeyboardButton("Am deja cod - Linkez acum", callback_data="login_prompt")],
                    [InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
                ]),
                parse_mode=ParseMode.MARKDOWN
            )

        elif callback_data == "login_prompt":
            # Prompt user to enter link code directly
            from telegram import ForceReply

            await query.edit_message_text(
                "**Conectare Cont ROA2WEB**\n\n"
                "Trimite-mi codul primit din aplicatia web.\n\n"
                "Poti trimite:\n"
                "- Doar codul: ABC12XYZ\n"
                "- Sau comanda: /start ABC12XYZ\n\n"
                "Codul expira in 15 minute.",
                parse_mode=ParseMode.MARKDOWN
            )

            # Send a follow-up message with ForceReply to prompt input
            await context.bot.send_message(
                chat_id=telegram_user_id,
                text="Scrie sau lipeste codul aici:",
                reply_markup=ForceReply(
                    selective=True,
                    input_field_placeholder="ABC12XYZ"
                )
            )

        elif callback_data == "login_back":
            # Go back to welcome message
            keyboard = InlineKeyboardMarkup([
                [InlineKeyboardButton("Cum obtin codul de link?", callback_data="login_help")],
                [InlineKeyboardButton("Am deja cod - Linkez contul", callback_data="login_prompt")]
            ])

            await query.edit_message_text(
                "**Bun venit la ROA2WEB Bot!**\n\n"
                "Sunt asistentul tau financiar pentru sistemul ERP ROA2WEB.\n\n"
                "**Pentru a incepe, trebuie sa-ti linkezi contul Telegram cu contul tau ROA2WEB.**\n\n"
                "Alege o optiune:",
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        # ========== NEW CALLBACKS (FAZA 4) ==========

        # NIVEL 1: Main Menu Buttons
        elif callback_data.startswith("menu:"):
            await handle_menu_callback(query, telegram_user_id, callback_data)

        # Action Buttons
        elif callback_data.startswith("action:"):
            await handle_action_callback(query, telegram_user_id, callback_data)

        # NIVEL 2: Client/Supplier Details
        elif callback_data.startswith("details:"):
            await handle_details_callback(query, telegram_user_id, callback_data)

        # NIVEL 3: Invoice Details
        elif callback_data.startswith("invoice:"):
            await handle_invoice_callback(query, telegram_user_id, callback_data)

        # Navigation Back
        elif callback_data.startswith("nav:back:"):
            await handle_navigation_back(query, telegram_user_id, callback_data)

        # ========== CACHE CALLBACKS (FAZA 6) ==========

        elif callback_data.startswith("cache_toggle:"):
            # Handle cache toggle button
            action = callback_data.split(":")[1]
            enabled = action == "on"

            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            try:
                client = get_backend_client()
                async with client:
                    await client.toggle_user_cache(jwt_token=jwt_token, enabled=enabled)

                status = "activat" if enabled else "dezactivat"
                message = f"✅ **Cache {status}** pentru tine.\n\n"

                if enabled:
                    message += "Queries vor fi servite din cache când e posibil."
                else:
                    message += "Toate queries vor merge direct la Oracle.\nFolosește /togglecache din nou pentru reactivare."

                # Add back button
                keyboard = InlineKeyboardMarkup([
                    [InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
                ])

                await query.edit_message_text(
                    message,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )
            except Exception as e:
                logger.error(f"Toggle cache callback error: {e}", exc_info=True)
                await query.answer("❌ Eroare la modificarea setării cache.", show_alert=True)

        elif callback_data.startswith("cache_clear:"):
            # Handle clear cache button
            scope = callback_data.split(":")[1]

            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            try:
                client = get_backend_client()

                if scope == "all":
                    # Clear all cache
                    async with client:
                        await client.invalidate_cache(jwt_token=jwt_token, company_id=None)
                    message = "✅ Cache invalidat pentru **toate companiile**.\n\nDatele vor fi refreshate la următoarea interogare."

                elif scope == "current":
                    # Clear only current company
                    session_manager = get_session_manager()
                    session = await session_manager.get_or_create_session(telegram_user_id)
                    company = session.get_active_company()

                    if not company:
                        await query.answer("Nu ai o companie selectată.", show_alert=True)
                        return

                    async with client:
                        await client.invalidate_cache(jwt_token=jwt_token, company_id=company['id'])
                    message = f"✅ Cache invalidat pentru **{company['name']}**.\n\nDatele vor fi refreshate la următoarea interogare."

                # Add back button
                keyboard = InlineKeyboardMarkup([
                    [InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
                ])

                await query.edit_message_text(
                    message,
                    reply_markup=keyboard,
                    parse_mode=ParseMode.MARKDOWN
                )
            except Exception as e:
                logger.error(f"Clear cache callback error: {e}", exc_info=True)
                await query.answer("❌ Eroare la ștergerea cache-ului.", show_alert=True)

        # ========== PAGINATION CALLBACKS ==========

        elif callback_data.startswith("clients_page:"):
            # Handle clients pagination
            page = int(callback_data.split(":")[1])

            # Get auth data and company
            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            session_manager = get_session_manager()
            session = await session_manager.get_or_create_session(telegram_user_id)
            company = session.get_active_company()

            # Get clients with maturity
            from backend.modules.telegram.bot.helpers import get_clients_with_maturity
            clients_data = await get_clients_with_maturity(company['id'], jwt_token)

            from backend.modules.telegram.bot.formatters import format_clients_balance_response
            from backend.modules.telegram.bot.menus import create_client_list_keyboard, format_response_with_company

            content = format_clients_balance_response(
                clients_data['clients'],
                clients_data['maturity']
            )
            response = format_response_with_company(content, company['name'])
            keyboard = create_client_list_keyboard(clients_data['clients'], page=page)

            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        elif callback_data.startswith("suppliers_page:"):
            # Handle suppliers pagination
            page = int(callback_data.split(":")[1])

            # Get auth data and company
            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            session_manager = get_session_manager()
            session = await session_manager.get_or_create_session(telegram_user_id)
            company = session.get_active_company()

            # Get suppliers with maturity
            from backend.modules.telegram.bot.helpers import get_suppliers_with_maturity
            suppliers_data = await get_suppliers_with_maturity(company['id'], jwt_token)

            from backend.modules.telegram.bot.formatters import format_suppliers_balance_response
            from backend.modules.telegram.bot.menus import create_supplier_list_keyboard, format_response_with_company

            content = format_suppliers_balance_response(
                suppliers_data['suppliers'],
                suppliers_data['maturity']
            )
            response = format_response_with_company(content, company['name'])
            keyboard = create_supplier_list_keyboard(suppliers_data['suppliers'], page=page)

            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        elif callback_data.startswith("invoices_page:"):
            # Handle invoices pagination
            # Format: invoices_page:PARTNER_TYPE:PARTNER_NAME:PAGE
            parts = callback_data.split(":")
            partner_type = parts[1]  # CLIENTI or FURNIZORI
            partner_name = parts[2]
            page = int(parts[3])

            # Get auth data and company
            auth_data = await get_user_auth_data(telegram_user_id)
            jwt_token = auth_data['jwt_token']

            session_manager = get_session_manager()
            session = await session_manager.get_or_create_session(telegram_user_id)
            company = session.get_active_company()

            # Get invoices for this partner
            if partner_type == "CLIENTI":
                from backend.modules.telegram.bot.helpers import get_client_invoices, get_clients_with_maturity
                invoices = await get_client_invoices(company['id'], partner_name, jwt_token)

                # Get client details
                clients_data = await get_clients_with_maturity(company['id'], jwt_token)
                partner = next((c for c in clients_data['clients'] if c['name'] == partner_name), None)

                from backend.modules.telegram.bot.formatters import format_client_detail_response
                content = format_client_detail_response(partner, invoices)
            else:
                from backend.modules.telegram.bot.helpers import get_supplier_invoices, get_suppliers_with_maturity
                invoices = await get_supplier_invoices(company['id'], partner_name, jwt_token)

                # Get supplier details
                suppliers_data = await get_suppliers_with_maturity(company['id'], jwt_token)
                partner = next((s for s in suppliers_data['suppliers'] if s['name'] == partner_name), None)

                from backend.modules.telegram.bot.formatters import format_supplier_detail_response
                content = format_supplier_detail_response(partner, invoices)

            from backend.modules.telegram.bot.menus import create_invoice_list_keyboard, format_response_with_company
            response = format_response_with_company(content, company['name'])
            keyboard = create_invoice_list_keyboard(invoices, partner_type, partner_name, page=page)

            await query.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

        elif callback_data == "noop":
            # No operation - just acknowledge
            pass

    except Exception as e:
        logger.error(f"Error in button_callback: {e}", exc_info=True)


# ============================================================================
# ERROR HANDLER
# ============================================================================

async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """
    Handle errors in bot operations.

    Args:
        update: Telegram update object
        context: Telegram context with error
    """
    logger.error(f"Update {update} caused error {context.error}", exc_info=context.error)

    # Try to send error message to user
    try:
        if update and update.effective_message:
            await update.effective_message.reply_text(
                "**A aparut o eroare tehnica**\n\n"
                "Te rog incearca din nou sau contacteaza support.\n\n"
                "Daca problema persista, foloseste /clear pentru a reseta conversatia.",
                parse_mode=ParseMode.MARKDOWN
            )
    except Exception as e:
        logger.error(f"Failed to send error message to user: {e}")


# ============================================================================
# COMMON HANDLER FUNCTIONS (pentru consistență comenzi/butoane)
# ============================================================================

async def _handle_expired_auth(query_or_update, telegram_user_id: int, auth_data: Optional[Dict[str, Any]]) -> bool:
    """
    Check if auth_data is None (token expired/refresh failed) and send user-friendly message.

    Args:
        query_or_update: Update (command) or CallbackQuery (button)
        telegram_user_id: Telegram user ID
        auth_data: Authentication data from get_user_auth_data()

    Returns:
        True if auth is expired (stop execution), False if auth is valid (continue)
    """
    if auth_data is None:
        logger.warning(f"Auth expired for user {telegram_user_id}, sending re-authentication message")

        # Create re-authentication message
        message = (
            "⚠️ **Sesiunea ta a expirat**\n\n"
            "Token-ul de autentificare a expirat și nu a putut fi reînnoit automat.\n\n"
            "**Pentru a continua:**\n"
            "1. Accesează aplicația web ROA2WEB\n"
            "2. Loginează-te cu contul tău Oracle\n"
            "3. Generează un nou cod de link pentru Telegram\n"
            "4. Trimite comanda `/start CODUL_TAU`\n\n"
            "_Sau folosește `/unlink` pentru a deconecta contul actual._"
        )

        # Send message based on source type
        from telegram import CallbackQuery
        if isinstance(query_or_update, CallbackQuery):
            # It's a button callback - transform menu to Login menu
            await query_or_update.answer("Sesiunea a expirat. Te rog să te reconectezi.", show_alert=True)

            # Transform the current message (menu) to Login menu
            from backend.modules.telegram.bot.menus import create_main_menu, pad_message_for_wide_buttons
            keyboard = create_main_menu(company_name=None, company_cui=None, is_authenticated=False)
            menu_text = pad_message_for_wide_buttons(
                "⚠️ **Sesiunea a expirat**\n\n"
                "Pentru a continua, apasă **Login**\n"
                "și urmează instrucțiunile."
            )

            await query_or_update.edit_message_text(
                menu_text,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        else:
            # It's a command (Update) - just send message
            await query_or_update.message.reply_text(message, parse_mode=ParseMode.MARKDOWN)

        return True  # Stop execution

    return False  # Continue execution


async def _handle_sold_view(
    query_or_update,
    telegram_user_id: int,
    company: Dict[str, Any],
    jwt_token: str,
    is_callback: bool = False
):
    """
    Common handler pentru sold view (dashboard).

    Folosit de:
    - Comanda /dashboard
    - Comanda /sold
    - Butonul menu:sold

    Args:
        query_or_update: Query (callback) sau Update (command)
        telegram_user_id: Telegram user ID
        company: Dict cu id, name, cui
        jwt_token: JWT token
        is_callback: True dacă e apelat din callback, False dacă e command
    """
    try:
        client = get_backend_client()
        async with client:
            data = await client.get_dashboard_data(
                company_id=company['id'],
                jwt_token=jwt_token
            )

        if not data:
            error_msg = "Eroare la incarcarea dashboard-ului."
            if is_callback:
                await query_or_update.edit_message_text(error_msg)
            else:
                await query_or_update.message.reply_text(error_msg)
            return

        from backend.modules.telegram.bot.formatters import format_dashboard_response, add_performance_footer
        from backend.modules.telegram.bot.menus import create_action_buttons, format_response_with_company

        # Extract cache metadata
        cache_hit = data.get('cache_hit', False)
        response_time_ms = data.get('response_time_ms', 0)
        cache_source = data.get('cache_source', None)

        content = format_dashboard_response(data)
        response = format_response_with_company(content, company['name'])

        # Add performance footer
        if response_time_ms > 0:
            response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
        keyboard = create_action_buttons("sold", show_export=False, show_refresh=False)

        if is_callback:
            await query_or_update.edit_message_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        else:
            await query_or_update.message.reply_text(
                response,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

    except Exception as e:
        logger.error(f"Error in _handle_sold_view: {e}", exc_info=True)
        error_msg = "Eroare la incarcarea dashboard-ului."
        if is_callback:
            await query_or_update.answer(error_msg, show_alert=True)
        else:
            await query_or_update.message.reply_text(error_msg)


async def _handle_selectcompany_view(
    query_or_update,
    telegram_user_id: int,
    jwt_token: str,
    is_callback: bool = False,
    page: int = 0,
    search_term: str = ""
):
    """
    Common handler pentru company selection cu paginare.

    Folosit de:
    - Comanda /selectcompany
    - Butonul menu:select_company
    - Callback-urile de paginare (select_company_page:N)

    Args:
        query_or_update: Query (callback) sau Update (command)
        telegram_user_id: Telegram user ID
        jwt_token: JWT token
        is_callback: True dacă e apelat din callback, False dacă e command
        page: Numărul paginii (0-indexed)
        search_term: Termen de căutare (opțional)
    """
    try:
        client = get_backend_client()
        async with client:
            companies = await client.get_user_companies(jwt_token=jwt_token)

        # Apply search filter if provided
        if search_term:
            from backend.modules.telegram.bot.helpers import search_companies_by_name
            companies = await search_companies_by_name(search_term, jwt_token)

            if not companies:
                error_msg = f"Nu am gasit companii care contin '{search_term}'.\n\n" \
                           "Incearca alt termen sau /selectcompany pentru lista completa."
                if is_callback:
                    await query_or_update.answer(error_msg, show_alert=True)
                else:
                    await query_or_update.message.reply_text(error_msg)
                return

        if not companies:
            error_msg = "Nu ai acces la nicio companie.\nContacteaza administratorul."
            if is_callback:
                await query_or_update.edit_message_text(
                    error_msg,
                    parse_mode=ParseMode.MARKDOWN
                )
            else:
                await query_or_update.message.reply_text(
                    error_msg,
                    parse_mode=ParseMode.MARKDOWN
                )
            return

        from backend.modules.telegram.bot.helpers import create_company_selection_keyboard_paginated
        keyboard = create_company_selection_keyboard_paginated(companies, page=page)

        message = f"**Selecteaza Compania**\n\n"
        if search_term:
            message += f"Rezultate '{search_term}' ({len(companies)}):"
        else:
            message += f"Companiile tale ({len(companies)}):"

        if is_callback:
            await query_or_update.edit_message_text(
                message,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )
        else:
            await query_or_update.message.reply_text(
                message,
                reply_markup=keyboard,
                parse_mode=ParseMode.MARKDOWN
            )

    except Exception as e:
        logger.error(f"Error in _handle_selectcompany_view: {e}", exc_info=True)
        error_msg = "A aparut o eroare. Te rog incearca din nou."
        if is_callback:
            await query_or_update.answer(error_msg, show_alert=True)
        else:
            await query_or_update.message.reply_text(error_msg)


# Export all handlers
__all__ = [
    'start_command',
    'help_command',
    'clear_command',
    'companies_command',
    'unlink_command',
    'selectcompany_command',
    'dashboard_command',
    'sold_command',
    'facturi_command',
    'trezorerie_command',
    # FAZA 3: New command handlers with button interface
    'menu_command',
    'trezorerie_casa_command',
    'trezorerie_banca_command',
    'clienti_command',
    'furnizori_command',
    'evolutie_command',
    # Text message handlers
    'handle_text_message',
    # FAZA 4: Callback helper functions
    'handle_menu_callback',
    'handle_action_callback',
    'handle_details_callback',
    'handle_invoice_callback',
    'handle_navigation_back',
    # Callback and error handlers
    'button_callback',
    'error_handler',
    # Common handler functions
    '_handle_sold_view',
    '_handle_selectcompany_view'
]
