import logging
from typing import Optional

from aiogram import F, Router, types
from sqlalchemy.ext.asyncio import AsyncSession

from bot.keyboards.inline.user_keyboards import (
    get_payment_method_keyboard,
    sale_mode_with_callback_context,
    subscription_options_callback,
)
from bot.middlewares.i18n import JsonI18n
from config.settings import Settings

router = Router(name="user_subscription_payments_selection_router")


@router.callback_query(F.data.startswith("subscribe_period:"))
async def select_subscription_period_callback_handler(
    callback: types.CallbackQuery,
    settings: Settings,
    i18n_data: dict,
    session: AsyncSession,
):
    current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
    i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
    get_text = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key

    if not i18n or not callback.message:
        try:
            await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
        except Exception:
            pass
        return

    traffic_packages = getattr(settings, "traffic_packages", {}) or {}
    stars_traffic_packages = getattr(settings, "stars_traffic_packages", {}) or {}
    traffic_mode = bool(getattr(settings, "traffic_sale_mode", False) or stars_traffic_packages)
    parts = callback.data.split(":")
    callback_context = parts[2] if len(parts) > 2 else None
    try:
        months = float(parts[1])
    except (ValueError, IndexError):
        logging.error(f"Invalid subscription period in callback_data: {callback.data}")
        try:
            await callback.answer(get_text("error_try_again"), show_alert=True)
        except Exception:
            pass
        return

    price_source = traffic_packages if traffic_mode else settings.subscription_options
    stars_price_source = (
        stars_traffic_packages if traffic_mode else settings.stars_subscription_options
    )

    price_rub = price_source.get(months)
    stars_price = stars_price_source.get(months)
    currency_symbol_val = settings.DEFAULT_CURRENCY_SYMBOL

    if price_rub is None:
        if traffic_mode and not price_source and stars_price is not None:
            from bot.payment_providers import iter_provider_specs

            currency_methods_enabled = any(
                spec.price_source != "stars"
                and spec.is_available_to_user(
                    settings,
                    user_id=callback.from_user.id,
                    require_configured=False,
                )
                for spec in iter_provider_specs()
            )
            if currency_methods_enabled:
                logging.error(
                    "Currency price missing for traffic option %s while fiat providers are enabled.",  # noqa: E501
                    months,
                )
                try:
                    await callback.answer(get_text("error_try_again"), show_alert=True)
                except Exception:
                    pass
                return
            price_rub = 0.0
            currency_symbol_val = "⭐"
        else:
            logging.error(
                f"Price not found for option {months} using {'traffic_packages' if traffic_mode else 'subscription_options'}."  # noqa: E501
            )
            try:
                await callback.answer(get_text("error_try_again"), show_alert=True)
            except Exception:
                pass
            return

    text_content = (
        get_text("choose_payment_method_traffic")
        if traffic_mode
        else get_text("choose_payment_method")
    )
    reply_markup = get_payment_method_keyboard(
        months,
        price_rub,
        stars_price,
        currency_symbol_val,
        current_lang,
        i18n,
        settings,
        sale_mode=sale_mode_with_callback_context(
            "traffic" if traffic_mode else "subscription", callback_context
        ),
        back_callback=subscription_options_callback(callback_context),
        user_id=callback.from_user.id,
    )

    try:
        await callback.message.edit_text(text_content, reply_markup=reply_markup)
    except Exception as e_edit:
        logging.warning(
            f"Edit message for payment method selection failed: {e_edit}. Sending new one."
        )
        await callback.message.answer(text_content, reply_markup=reply_markup)
    try:
        await callback.answer()
    except Exception:
        pass
