use super::*;
use crate::ui::prelude::*;
use crate::ui::user::merge_account::*;

pub async fn callback_handler(
    bot: Bot,
    profile: Profile,
    dialogue: MasterDialogue,
    q: CallbackQuery,
    settings: HandlerSettings,
) -> HandlerResult {
    let ln = settings.language;

    let Some(data) = q.data.clone() else {
        log::error!("Callback data is None");
        return Err("Callback data is None".into());
    };

    let Some(message) = get_callback_message(q.clone()) else {
        log::error!("Message does not exist");
        return Err("Message does not exist".into());
    };

    use Callback::*;
    let callback: Callback = serde_json::from_str(&data)?;
    match callback {
        UpdateProfile => {
            bot.answer_callback_query(q.id.clone()).await?;
            if let Err(e) = invalidate_profile_cache(&dialogue).await {
                log::warn!("Failed to invalidate profile cache: {}", e);
            }
            profile_handler(bot, dialogue, message, profile, settings).await?;
        }
        Noop => {
            bot.answer_callback_query(q.id.clone()).await?;
        }
        BuyTraffic { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            
            update_state_preserving_cache(&dialogue, UserStateKind::Purchase).await?;
            
            match pool {
                Some(pool) => {
                    purchase::show_purchase_summary(bot, message.chat.id, message.id, pool, None, None, ln).await?;
                }
                None => {
                    select_pool_handler_constructor(
                        bot,
                        message,
                        |pool| PurchaseCallback::SelectPool { pool }.to_string(),
                        Some(Callback::BackFromBuying.to_string()),
                        SelectPoolHandlerSettings::from(settings.force_behavior(ForceHandlerBehavior::EditMessage))
                    ).await?;
                }
            }
        }
        Api => {
            bot.answer_callback_query(q.id.clone()).await?;
            api_handler(bot, message, settings).await?;
        }
        BackFromBuying => {
            bot.answer_callback_query(q.id.clone()).await?;
            update_state_preserving_cache(&dialogue, UserStateKind::UserMenu).await?;
            get_back_from_buying(bot, dialogue, message, profile, settings).await?;
        }
        DeleteThisMessage => {
            bot.answer_callback_query(q.id.clone()).await?;
            bot.delete_message(message.chat.id, message.id).await?;
        }
        ActivatePromo => {
            bot.answer_callback_query(q.id.clone()).await?;
            activate_promo(bot, dialogue, message, settings).await?;
        }
        Referral => {
            bot.answer_callback_query(q.id.clone()).await?;
            referral_handler(bot, dialogue, message, settings).await?;
        }
        ChangeLanguage => {
            bot.answer_callback_query(q.id.clone()).await?;
            let ln = if ln == Language::Ru {
                let ln = Language::En;
                change_language_and_invalidate_cache(&dialogue, message.chat.id.0, ln).await?;
                ln
            } else {
                let ln = Language::Ru;
                change_language_and_invalidate_cache(&dialogue, message.chat.id.0, ln).await?;
                ln
            };

            let msg = strfmt!(t8x!(Ru, "Язык изменен на {language}", &ln), language => ln.to_string())?;

            let keyboard = make_menu_keyboard(ln);
            bot.send_message(message.chat.id, msg)
                .reply_markup(keyboard)
                .await?;

            profile_handler(
                bot,
                dialogue,
                message,
                profile,
                settings.force_behavior(ForceHandlerBehavior::DeleteMessage).with_language(ln)
            ).await?;
        }
        BindEmail => {
            bot.answer_callback_query(q.id.clone()).await?;
            
            let back_button = InlineKeyboardButton::callback(
                t8x!(Ru, "🔙Назад🔙", &ln),
                Callback::BackToProfile.to_string()
            );
            let keyboard = InlineKeyboardMarkup::new(vec![vec![back_button]]);
            
            bot.edit_message_text(
                message.chat.id,
                message.id,
                t8x!(Ru, "Введите вашу почту:", &ln)
            )
            .reply_markup(keyboard)
            .await?;
            
            update_state_preserving_cache(&dialogue, UserStateKind::ReceiveEmail).await?;
        }
        AdvancedFeatures => {
            bot.answer_callback_query(q.id.clone()).await?;
            advanced_features_handler(bot, dialogue, message, profile, settings).await?;
        }
        ResellerProfile => {
            bot.answer_callback_query(q.id.clone()).await?;
            reseller_profile_handler(bot, dialogue, message, settings).await?;
        }
        MergeAccount => {
            bot.answer_callback_query(q.id.clone()).await?;
            merge_account_handler(bot, dialogue, message, settings).await?;
        }
        Online { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            send_pool_online(bot, message, pool, settings).await?;
        }
        BackFromOnline => {
            bot.answer_callback_query(q.id.clone()).await?;
            bot.delete_message(message.chat.id, message.id).await?;
        }
        BackToProfile => {
            bot.answer_callback_query(q.id.clone()).await?;
            profile_handler(bot, dialogue, message, profile, settings).await?;
        }
        CaptchaAnswer { value } => {
            if let Some(MasterState { user_kind: UserStateKind::ReceiveCaptcha { start, captcha_text }, .. }) = dialogue.get().await? {
                if value == captcha_text {
                    bot.answer_callback_query(q.id.clone()).await?;
                    bot.edit_message_caption(message.chat.id, message.id)
                        .caption(t8x!(Ru, "✅ Капча решена правильно!", &ln))
                        .reply_markup(InlineKeyboardMarkup::default())
                        .await?;
                    
                    show_language_selection(bot.clone(), dialogue.clone(), message.clone(), start, settings).await?;
                } else {
                    bot.answer_callback_query(q.id.clone()).await?;
                    bot.edit_message_caption(message.chat.id, message.id)
                        .caption(t8x!(Ru, "❌ Капча неверна, попробуйте ещё раз", &ln))
                        .reply_markup(InlineKeyboardMarkup::default())
                        .await?;
                    
                    captcha_check_handler(bot, dialogue, message, start, settings).await?;
                }
            } else {
                bot.answer_callback_query(q.id.clone()).await?;
                bot.send_message(message.chat.id, t8x!(Ru, "Ошибка: неверное состояние диалога", &ln))
                    .await?;
            }
        }
        SelectLanguage {
            language,
        } => {
            bot.answer_callback_query(q.id.clone()).await?;

            let user = q.from;

            if let Some(MasterState { user_kind: UserStateKind::ReceiveLanguage { referral }, .. }) = dialogue.get().await? {
                match api::upsert_tg_user(user.id.0, user.first_name, user.last_name, user.username, referral).await {
                    Ok(_) => {
                        change_language_and_invalidate_cache(&dialogue, message.chat.id.0, language).await?;
                        
                        
                        bot.edit_message_text(message.chat.id, message.id, t8x!(Ru, "Вы выбрали русский язык", &ln)).await?;
                        
                        let new_settings = settings.with_language(language);
                        start_message_handler(bot.clone(), dialogue.clone(), message.clone(), new_settings).await?;
                    }
                    Err(e) => {
                        log::error!("{}", e);
                        error_handler(bot, dialogue, message, settings).await?;
                    }
                }
            } else {
                if ln == Language::Ru {
                    change_language_and_invalidate_cache(&dialogue, message.chat.id.0, Language::En).await?;
                } else {
                    change_language_and_invalidate_cache(&dialogue, message.chat.id.0, Language::Ru).await?;
                }
                profile_handler(
                    bot,
                    dialogue,
                    message,
                    profile,
                    settings.force_behavior(ForceHandlerBehavior::DeleteMessage)
                ).await?;
            }
        }
        // Новые обработчики для управления прокси
        ManageProxy => {
            bot.answer_callback_query(q.id.clone()).await?;
            manage_proxy_handler(bot, message, settings, profile).await?;
        }
        SelectPoolForManagement { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            proxy_management_menu_handler(bot, message, dialogue, pool, settings, profile).await?;
        }
        ChangePasswordForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            change_password_for_pool_handler(bot, message, dialogue, pool, settings).await?;
        }
        CheckStatsForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            check_stats_for_pool_handler(bot, message, pool, settings).await?;
        }
        CheckStatsWeekForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            check_stats_week_for_pool_handler(bot, message, pool, settings).await?;
        }
        CheckStatsMonthForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            check_stats_month_for_pool_handler(bot, message, pool, settings).await?;
        }
        BackToStatsMenu { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            check_stats_for_pool_handler(bot, message, pool, settings).await?;
        }
        ManageWhitelistForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            manage_whitelist_for_pool_handler(bot, message, pool, settings).await?;
        }
        ViewWhitelistForPool { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            view_whitelist_for_pool_handler(bot, message, pool, settings).await?;
        }
        AddIPToWhitelist { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            add_ip_to_whitelist_handler(bot, message, dialogue, pool, settings).await?;
        }
        RemoveIPFromWhitelist { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            remove_ip_from_whitelist_handler(bot, message, dialogue, pool, settings).await?;
        }
        BackToWhitelistMenu { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            manage_whitelist_for_pool_handler(bot, message, pool, settings).await?;
        }
        ManageDefaultProxySettings { pool } => {
            bot.answer_callback_query(q.id.clone()).await?;
            manage_default_proxy_settings_handler(bot, message, pool, dialogue, settings).await?;
        }
        SetAccountPassword => {
            bot.answer_callback_query(q.id.clone()).await?;
            set_account_password_handler(bot, dialogue, message, settings).await?;
        }
        WebsiteLogin => {
            website_login_handler(bot, message, settings).await?;
        }
        WithdrawRequest => {
            bot.answer_callback_query(q.id.clone()).await?;
            
            let back_button = InlineKeyboardButton::callback(
                t8x!(Ru, "🔙Назад🔙", &ln),
                Callback::BackToProfile.to_string()
            );
            let keyboard = InlineKeyboardMarkup::new(vec![vec![back_button]]);
            
            bot.edit_message_text(
                message.chat.id,
                message.id,
                t8x!(Ru, "💰 Введите сумму для вывода (в USD):\n\n💳 После ввода суммы вам нужно будет указать реквизиты для вывода средств (номер карты, банк и т.д.)", &ln)
            )
            .reply_markup(keyboard)
            .await?;
            
            update_state_preserving_cache(&dialogue, UserStateKind::ReceiveWithdrawAmount).await?;
        }
        ConfirmWithdraw { amount } => {
            bot.answer_callback_query(q.id.clone()).await?;
            
            let comment = if let Ok(Some(state)) = dialogue.get().await {
                if let UserStateKind::ConfirmWithdraw { amount: stored_amount, comment: stored_comment } = state.user_kind {
                    if (stored_amount - amount).abs() < f64::EPSILON {
                        Some(stored_comment)
                    } else {
                        None
                    }
                } else {
                    None
                }
            } else {
                None
            };
            
            let comment = match comment {
                Some(c) => c,
                None => {
                    log::error!("Failed to retrieve comment from dialogue state for withdraw request");
                    bot.edit_message_text(
                        message.chat.id,
                        message.id,
                        t8x!(Ru, "❌ Ошибка: не удалось получить данные заявки. Попробуйте создать заявку заново.", &ln)
                    )
                    .reply_markup(make_inline_keyboard(vec![(t8x!(Ru, "🔙Назад🔙", &ln), Callback::BackToProfile).into()], 1))
                    .await?;
                    return Ok(());
                }
            };
            
            bot.edit_message_text(
                message.chat.id,
                message.id,
                t8x!(Ru, "⏳ Обрабатываем запрос на вывод средств...", &ln)
            )
            .reply_markup(InlineKeyboardMarkup::default())
            .await?;
            
            match api::create_referral_withdrawal_request(message.chat.id.0, amount, comment.clone()).await {
                Ok(response) => {
                    let success_message = strfmt!(
                        t8x!(Ru, r#"
                            ✅ Запрос на вывод средств успешно создан!
                            
                            📋 ID запроса: #{request_id}
                            💵 Сумма: ${amount:.2}
                            💳 Реквизиты: {comment}
                            📊 Статус: {status}
                            
                            💬 {message}
                        "#, &ln),
                        request_id => response.request_id,
                        amount => response.amount,
                        comment => comment,
                        status => response.status,
                        message => response.message
                    )?;
                    
                    let back_button = InlineKeyboardButton::callback(
                        t8x!(Ru, "🔙Назад🔙", &ln),
                        Callback::BackToProfile.to_string()
                    );
                    let keyboard = InlineKeyboardMarkup::new(vec![vec![back_button]]);
                    
                    bot.edit_message_text(message.chat.id, message.id, success_message)
                        .reply_markup(keyboard)
                        .await?;
                }
                Err(e) => {
                    log::error!("Failed to create withdrawal request: {}", e);
                    
                    let error_message = t8x!(Ru, "❌ Произошла ошибка при создании запроса на вывод средств. Попробуйте позже или обратитесь в поддержку.", &ln);
                    
                    let back_button = InlineKeyboardButton::callback(
                        t8x!(Ru, "🔙Назад🔙", &ln),
                        Callback::BackToProfile.to_string()
                    );
                    let keyboard = InlineKeyboardMarkup::new(vec![vec![back_button]]);
                    
                    bot.edit_message_text(message.chat.id, message.id, error_message)
                        .reply_markup(keyboard)
                        .await?;
                }
            }
        }
    }

    Ok(())
}
