use super::*;
use crate::ui::prelude::*;
use rust_shared::i18n::Language;

pub async fn callback_handler(
    bot: Bot,
    dialogue: MasterDialogue,
    q: CallbackQuery,
    update: Update,
    settings: HandlerSettings,
) -> HandlerResult {
    let Some(data) = q.data.clone() else {
        log::error!("AdminAdminCallback data is None");
        return Err("AdminAdminCallback data is None".into());
    };

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

    use AdminCallback::*;
    let callback: AdminCallback = serde_json::from_str(&data)?;
    match callback {
        AdminMenu => {
            bot.delete_message(message.chat.id, message.id).await?;
            admin_entrypoint(bot, dialogue, message, settings).await?
        }
        StatsToday => {
            daily_stats_handler(bot, dialogue, message, true).await?
        }
        StatsByDate => {
            daily_stats_handler(bot, dialogue, message, false).await?
        }
        PromoSelectPool { pool } => {
            admin_promo_create_handler(bot, dialogue, message, pool).await?
        }
        DeletePromos => {
            show_delete_promos_page(bot, dialogue, update, message, 0).await?
        }
        DeletePromosPage { page } => {
            handle_delete_promos_page(bot, dialogue, message, update, page)
                .await?
        }
        DeletePromo { promo_name } => {
            handle_delete_promo_confirmation(bot, message, promo_name)
                .await?
        }
        ConfirmDeletePromo { promo_name } => {
            handle_confirm_delete_promo(
                bot, dialogue, message, promo_name,
            )
            .await?
        }
        ChangeReferralPercent => {
            let Some(state) = dialogue.get().await? else {
                return Err("No state found in dialogue".into());
            };
            let AdminStateKind::StatsReceiveUserId { user_id } = state.admin_kind else {
                return Err("Expected StatsReceiveUserId state".into());
            };
            let Some(user_id) = user_id else {
                return Err("User ID is None".into());
            };

            let message_text = format!(
                indoc! {r#"
                    ⚙️ <b>Изменение процента реферальной программы для пользователя</b>
                    
                    <b>🆔 Пользователь:</b> {}
                    📝 Введите новый процент реферальной программы (например: 0.05, что будет 5%):
                    
                    💡 <i>Этот процент будет установлен только для данного пользователя</i>
                "#},
                user_id
            );

            bot.edit_message_text(message.chat.id, message.id, message_text)
                .parse_mode(teloxide::types::ParseMode::Html)
                .reply_markup(make_inline_keyboard(
                    vec![("🔙 Отмена", AdminCallback::ShowUserProfile { user_id: user_id.clone() }).into()],
                    1,
                ))
                .await?;

            dialogue.update_admin_kind(AdminStateKind::ReceiveUserReferralPercent { user_id }).await?;
        }
        AddTraffic { pool } => {
            let Some(state) = dialogue.get().await? else {
                return Err("No state found in dialogue".into());
            };
            let AdminStateKind::StatsReceiveUserId { user_id } = state.admin_kind else {
                return Err("Expected StatsReceiveUserId state".into());
            };
            let Some(user_id) = user_id else {
                return Err("User ID is None".into());
            };

            match pool {
                Some(pool) => {
                    bot.edit_message_text(
                        message.chat.id,
                        message.id,
                        format!(
                            "📊 <b>Добавление трафика</b>\n\n<b>Пользователь:</b> <code>{}</code>\n<b>Пул:</b> <code>{}</code>\n\n💬 Введите количество ГБ трафика для добавления:",
                            user_id,
                            pool.display_name(&Language::Ru)
                        )
                    )
                    .parse_mode(teloxide::types::ParseMode::Html)
                    .reply_markup(make_inline_keyboard(
                        vec![("🔙 Отмена", AdminCallback::AdminMenu).into()],
                        1,
                    ))
                    .await?;
                    
                    dialogue.update_admin_kind(AdminStateKind::AddTrafficReceiveAmount { user_id, pool }).await?;
                }
                None => {
                    select_pool_handler_constructor(
                        bot, 
                        message, 
                        |pool| AdminCallback::AddTraffic { pool: Some(pool) }.to_string(), 
                        Some(Callback::DeleteThisMessage.to_string()),
                        SelectPoolHandlerSettings::from(settings)
                        .include_pools(PoolType::all())
                        .with_message(t8x!("<b>Select pool</b>", &settings.language)))
                    .await?
                }
            }
        }
        UserWeeklyStats { pool } => {
            handle_user_detailed_stats(bot, message, pool, dialogue, "week").await?
        }
        UserMonthlyStats { pool } => {
            handle_user_detailed_stats(bot, message, pool, dialogue, "month").await?
        }
        UserWeeklyStatsPoolChoice { pools } => {
            select_pool_handler_constructor(
                bot, 
                message, 
                |pool| AdminCallback::UserWeeklyStats { pool }.to_string(), 
                Some(Callback::DeleteThisMessage.to_string()),
                SelectPoolHandlerSettings::from(settings)
                .include_pools(pools)
                .with_message(t8x!("<b>Only pools with purchased traffic available</b>", &settings.language)))
            .await?
        }
        UserMonthlyStatsPoolChoice { pools } => {
            select_pool_handler_constructor(
                bot, 
                message, 
                |pool| AdminCallback::UserMonthlyStats { pool }.to_string(), 
                Some(Callback::DeleteThisMessage.to_string()),
                SelectPoolHandlerSettings::from(settings)
                .include_pools(pools)
                .with_message(t8x!("<b>Only pools with purchased traffic available</b>", &settings.language)))
            .await?
        }
        // /admin -> "Promo"
        PromoMenu => {
            bot.delete_message(message.chat.id, message.id).await?;
            show_promo_menu(bot, dialogue, message, settings).await?
        }
        // /admin -> "Banner"
        BannerMenu => {
            bot.delete_message(message.chat.id, message.id).await?;
            show_banner_menu(bot, dialogue, message, settings).await?
        }
        // /admin -> "Preferences"
        PreferencesMenu => {
            bot.delete_message(message.chat.id, message.id).await?;
            show_preferences_menu(bot, dialogue, message, settings).await?
        }
        DevelopmentBlogPage { page } => {
            show_development_blog_page(bot, dialogue, message, page).await?
        }
        ChangePricePool { pool } => {
            handle_change_price_pool(bot, dialogue, message, pool).await?
        }
        DropBalance { pool } => {
            let Some(state) = dialogue.get().await? else {
                return Err("No state found in dialogue".into());
            };
            let AdminStateKind::StatsReceiveUserId { user_id } = state.admin_kind else {
                return Err("Expected StatsReceiveUserId state".into());
            };
            let Some(user_id) = user_id else {
                return Err("User ID is None".into());
            };

            match pool {
                Some(pool) => {
                    handle_drop_balance_confirmation(bot, message, user_id, pool).await?
                }
                None => {
                    select_pool_handler_constructor(
                        bot,
                        message,
                        |pool| AdminCallback::DropBalance { pool: Some(pool) }.to_string(),
                        Some(Callback::DeleteThisMessage.to_string()),
                        SelectPoolHandlerSettings::from(settings)
                        .include_pools(PoolType::all())
                        .with_message(t8x!("<b>Select pool to drop balance</b>", &settings.language)))
                    .await?
                }
            }
        }
        ConfirmDropBalance { user_id, pool } => {
            handle_confirm_drop_balance(bot, dialogue, message, user_id, pool).await?
        }
        SourceLinksMenu => {
            show_source_links(bot, dialogue, message).await?
        }
        SourceLinksPage { page } => {
            handle_source_links_page(bot, dialogue, message, page).await?
        }
        SourceLinksClearSearch => {
            handle_source_links_clear_search(bot, dialogue, message).await?
        }
        SourceLinkDetails { link_value } => {
            handle_source_link_details(bot, dialogue, message, link_value).await?
        }
        SourceLinkExportJson { link_value } => {
            handle_source_link_export_json(bot, dialogue, message, link_value).await?
        }
        SourceLinkExportCsv { link_value } => {
            handle_source_link_export_csv(bot, dialogue, message, link_value).await?
        }
        SourceLinksCreate => {
            handle_source_links_create(bot, dialogue, message).await?
        }
        BroadcastMenu => {
            show_broadcast_menu(bot, dialogue, message).await?
        }
        BroadcastToAll => {
            start_broadcast_with_audience(bot, dialogue, message, false).await?
        }
        BroadcastToWithoutPurchases => {
            start_broadcast_with_audience(bot, dialogue, message, true).await?
        }
        BroadcastConfirm { users_without_purchases } => {
            handle_broadcast_confirm_callback(bot, dialogue, message, users_without_purchases).await?
        }
        BroadcastTest { users_without_purchases } => {
            handle_broadcast_test_callback(bot, dialogue, message, users_without_purchases).await?
        }
        PaymentSystemsMenu => {
            show_payment_systems_menu(bot, dialogue, message).await?
        }
        PaymentSystemToggle { name } => {
            handle_payment_system_toggle(bot, dialogue, message, name).await?
        }
        PaymentSystemEditDescription { name } => {
            handle_payment_system_edit_description(bot, dialogue, message, name).await?
        }
        PaymentSystemConfirmToggle { name, enabled } => {
            handle_payment_system_confirm_toggle(bot, dialogue, message, name, enabled).await?
        }
        ShowUserProfile { user_id } => {
            log::trace!("AdminCallback ShowUserProfile {{ {user_id} }}");
            dialogue.update_admin_kind(AdminStateKind::StatsReceiveUserId { user_id: Some(user_id.clone()) }).await?;
            super::user_stats_handler(bot, dialogue, message, user_id).await?;
        }
        ConfirmTranslation => {
            log::trace!("AdminCallback ConfirmTranslation");
            handle_translation_confirmation(bot, message, dialogue).await?;
        }
        CancelTranslation => {
            log::trace!("AdminCallback CancelTranslation");
            fix_i18n_handler(bot, message, dialogue).await?;
        }
        WithdrawRequestsMenu => {
            show_withdraw_requests_page(bot, dialogue, message, 0, None).await?
        }
        WithdrawRequestsPage { page } => {
            handle_withdraw_requests_page(bot, dialogue, message, page).await?
        }
        WithdrawRequestDetails { request_id } => {
            handle_withdraw_request_details(bot, dialogue, message, request_id).await?
        }
        WithdrawRequestApprove { request_id } => {
            handle_withdraw_request_action(bot, dialogue, message, request_id, "approved").await?
        }
        WithdrawRequestReject { request_id } => {
            handle_withdraw_request_action(bot, dialogue, message, request_id, "rejected").await?
        }
        WithdrawRequestCancel { request_id } => {
            handle_withdraw_request_action(bot, dialogue, message, request_id, "cancelled").await?
        }
        WithdrawRequestForce { request_id } => {
            handle_withdraw_request_force(bot, dialogue, message, request_id).await?
        }
        ChangeResellerTraffic { user_id } => {
            handle_reseller_traffic_change(bot, dialogue, message, user_id).await?
        }
    }

    Ok(())
}
