use crate::ui::prelude::*;

pub async fn show_withdraw_requests(
    bot: Bot,
    dialogue: MasterDialogue,
    msg: Message,
) -> HandlerResult {
    show_withdraw_requests_page(bot, dialogue, msg, 0, None).await
}

pub async fn show_withdraw_requests_page(
    bot: Bot,
    dialogue: MasterDialogue,
    msg: Message,
    page: usize,
    search_query: Option<String>,
) -> HandlerResult {
    let loading_msg = bot.send_message(msg.chat.id, "⏳ Загружаем заявки на вывод...")
        .await?;

    match api::get_withdraw_requests(page, 20).await {
        Ok(withdraw_requests) => {
            if withdraw_requests.is_empty() && page == 0 {
                bot.edit_message_text(
                    loading_msg.chat.id,
                    loading_msg.id,
                    "📭 Заявок на вывод не найдено"
                )
                .reply_markup(make_inline_keyboard(
                    vec![("🔙 Вернуться в меню", AdminCallback::AdminMenu).into()],
                    1,
                ))
                .await?;
                return Ok(());
            }

            let message = format_withdraw_requests_message(&withdraw_requests, page);
            let keyboard = make_withdraw_requests_keyboard(&withdraw_requests, page);

            bot.edit_message_text(loading_msg.chat.id, loading_msg.id, message)
                .parse_mode(teloxide::types::ParseMode::Html)
                .reply_markup(keyboard)
                .await?;

            dialogue.update_admin_kind(AdminStateKind::WithdrawRequests { page, search_query }).await?;
        }
        Err(e) => {
            log::error!("Failed to get withdraw requests: {}", e);
            bot.edit_message_text(
                loading_msg.chat.id,
                loading_msg.id,
                format!("❌ Ошибка при загрузке заявок: {}", e),
            )
            .reply_markup(make_inline_keyboard(
                vec![("🔙 Вернуться в меню", AdminCallback::AdminMenu).into()],
                1,
            ))
            .await?;
        }
    }

    Ok(())
}

fn format_withdraw_requests_message(requests: &[WithdrawRequest], page: usize) -> String {
    let mut message = format!(
        "💳 <b>Заявки на вывод средств</b> (Страница {})\n\n",
        page + 1
    );

    if requests.is_empty() {
        message.push_str("📭 Заявки не найдены");
        return message;
    }

    for (i, request) in requests.iter().enumerate() {
        let status_emoji = match request.status.as_str() {
            "pending" => "⏳",
            "approved" => "✅",
            "rejected" => "❌",
            "cancelled" => "🚫",
            "completed" => "✔️",
            _ => "❓",
        };

        message.push_str(&format!(
            "{}. {} <b>#{}</b>\n   💰 <code>${:.2}</code>\n   👤 <code>{}</code>\n   📅 {}\n   📝 {}\n\n",
            page * 20 + i + 1,
            status_emoji,
            request.id,
            request.amount_usd(),
            request.user_id,
            request.created_at.split('T').next().unwrap_or(&request.created_at),
            if request.comment.is_empty() { "Без комментария" } else { &request.comment }
        ));
    }

    message.push_str("Выберите заявку для подробностей:");
    message
}

fn make_withdraw_requests_keyboard(
    requests: &[WithdrawRequest],
    page: usize,
) -> teloxide::types::InlineKeyboardMarkup {
    let mut keyboard = teloxide::types::InlineKeyboardMarkup::default();

    for chunk in requests.chunks(2) {
        let mut row = Vec::new();
        for request in chunk {
            let status_emoji = match request.status.as_str() {
                "pending" => "⏳",
                "approved" => "✅",
                "rejected" => "❌",
                "cancelled" => "🚫",
                "completed" => "✔️",
                _ => "❓",
            };

            let button_text = format!("{} #{} (${:.2})", status_emoji, request.id, request.amount_usd());
            row.push(teloxide::types::InlineKeyboardButton::callback(
                button_text,
                AdminCallback::WithdrawRequestDetails {
                    request_id: request.id,
                }
                .to_string(),
            ));
        }
        keyboard = keyboard.append_row(row);
    }

    let mut nav_buttons = Vec::new();

    if page > 0 {
        nav_buttons.push(teloxide::types::InlineKeyboardButton::callback(
            "⬅️ Предыдущая",
            AdminCallback::WithdrawRequestsPage { page: page - 1 }.to_string(),
        ));
    }

    if requests.len() == 20 {
        nav_buttons.push(teloxide::types::InlineKeyboardButton::callback(
            "Следующая ➡️",
            AdminCallback::WithdrawRequestsPage { page: page + 1 }.to_string(),
        ));
    }

    if !nav_buttons.is_empty() {
        keyboard = keyboard.append_row(nav_buttons);
    }

    keyboard = keyboard.append_row(vec![teloxide::types::InlineKeyboardButton::callback(
        "🔙 Вернуться в меню",
        AdminCallback::AdminMenu.to_string(),
    )]);

    keyboard
}

pub async fn withdraw_requests_state_handler(
    bot: Bot,
    msg: Message,
    dialogue: MasterDialogue,
    (page, search_query): (usize, Option<String>),
) -> HandlerResult {
    show_withdraw_requests_page(bot, dialogue, msg, page, search_query).await
}

pub async fn handle_withdraw_requests_page(
    bot: Bot,
    dialogue: MasterDialogue,
    msg: Message,
    page: usize,
) -> HandlerResult {
    show_withdraw_requests_page(bot, dialogue, msg, page, None).await
}

pub async fn handle_withdraw_request_details(
    bot: Bot,
    _dialogue: MasterDialogue,
    msg: Message,
    request_id: i64,
) -> HandlerResult {
    bot.edit_message_text(
        msg.chat.id,
        msg.id,
        "⏳ Загружаю детали заявки..."
    )
    .await?;

    match api::get_withdraw_requests(0, 1000).await {
        Ok(requests) => {
            if let Some(request) = requests.iter().find(|r| r.id == request_id) {
                let status_emoji = match request.status.as_str() {
                    "pending" => "⏳",
                    "approved" => "✅",
                    "rejected" => "❌",
                    "cancelled" => "🚫",
                    "completed" => "✔️",
                    _ => "❓",
                };

                let status_text = match request.status.as_str() {
                    "pending" => "Ожидает рассмотрения",
                    "approved" => "Одобрена",
                    "rejected" => "Отклонена",
                    "cancelled" => "Отменена",
                    "completed" => "Завершена",
                    _ => &request.status,
                };

                let mut details_message = format!(
                    indoc! {r#"
                        💳 <b>Детали заявки на вывод #{}</b>
                        
                        👤 <b>Пользователь:</b> <code>{}</code>
                        💰 <b>Сумма:</b> <code>${:.2}</code>
                        {} <b>Статус:</b> {}
                        📅 <b>Создана:</b> {}
                        📝 <b>Комментарий:</b> {}
                    "#},
                    request.id,
                    request.user_id,
                    request.amount_usd(),
                    status_emoji,
                    status_text,
                    request.created_at.split('T').next().unwrap_or(&request.created_at),
                    if request.comment.is_empty() { "Без комментария" } else { &request.comment }
                );

                if request.status == "pending" {
                    match api::get_profile_with_optional_headers(request.user_id.clone(), None, None).await {
                        Ok(profile) => {
                            let balance_info = format!(
                                "\n\n💰 <b>Текущий реферальный баланс:</b> <code>${:.2}</code>",
                                profile.referral_balance
                            );
                            details_message.push_str(&balance_info);
                            
                            if profile.referral_balance < request.amount_usd() {
                                let warning = format!(
                                    "\n⚠️ <b>Внимание:</b> Недостаточно средств! Требуется ${:.2}, доступно ${:.2}",
                                    request.amount_usd(),
                                    profile.referral_balance
                                );
                                details_message.push_str(&warning);
                            }
                        }
                        Err(e) => {
                            log::warn!("Failed to get user profile for balance check: {}", e);
                            let balance_warning = "\n\n⚠️ <b>Не удалось получить баланс пользователя</b>";
                            details_message.push_str(balance_warning);
                        }
                    }
                }

                let mut keyboard = teloxide::types::InlineKeyboardMarkup::default();

                if request.status == "pending" {
                    keyboard = keyboard.append_row(vec![
                        teloxide::types::InlineKeyboardButton::callback(
                            "✅ Готово",
                            AdminCallback::WithdrawRequestApprove { request_id }.to_string(),
                        ),
                        teloxide::types::InlineKeyboardButton::callback(
                            "❌ Отклонить",
                            AdminCallback::WithdrawRequestReject { request_id }.to_string(),
                        ),
                    ]);
                }

                keyboard = keyboard.append_row(vec![
                    teloxide::types::InlineKeyboardButton::callback(
                        "🔙 К списку заявок",
                        AdminCallback::WithdrawRequestsMenu.to_string(),
                    )
                ]);

                bot.edit_message_text(msg.chat.id, msg.id, details_message)
                    .parse_mode(teloxide::types::ParseMode::Html)
                    .reply_markup(keyboard)
                    .await?;
            } else {
                bot.edit_message_text(
                    msg.chat.id,
                    msg.id,
                    "❌ Заявка не найдена"
                )
                .reply_markup(make_inline_keyboard(
                    vec![("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into()],
                    1,
                ))
                .await?;
            }
        }
        Err(e) => {
            log::error!("Failed to get withdraw request details: {}", e);
            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!("❌ Ошибка при загрузке деталей: {}", e),
            )
            .reply_markup(make_inline_keyboard(
                vec![("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into()],
                1,
            ))
            .await?;
        }
    }

    Ok(())
}

pub async fn handle_withdraw_request_force(
    bot: Bot,
    _dialogue: MasterDialogue,
    msg: Message,
    request_id: i64,
) -> HandlerResult {
    bot.edit_message_text(
        msg.chat.id,
        msg.id,
        format!("⚠️ Принудительно одобряем заявку #{}...\n\n💡 <b>Внимание:</b> Это приведет к отрицательному балансу пользователя!", request_id),
    )
    .parse_mode(teloxide::types::ParseMode::Html)
    .await?;

    match api::update_withdraw_request_status(request_id, "approved".to_string(), true).await {
        Ok(()) => {
            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!(
                    "⚠️ <b>Заявка #{} принудительно одобрена!</b>\n\n\
                    💡 <b>Важно:</b> Баланс пользователя стал отрицательным.",
                    request_id
                ),
            )
            .parse_mode(teloxide::types::ParseMode::Html)
            .reply_markup(make_inline_keyboard(
                vec![
                    ("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into(),
                    ("🏠 Главное меню", AdminCallback::AdminMenu).into()
                ],
                1,
            ))
            .await?;
        }
        Err(api::WithdrawRequestError::InsufficientBalance { request_id, error_details }) => {
            log::error!("Still insufficient balance even with force for withdraw request {}: {}", request_id, error_details);
            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!("❌ <b>Ошибка принудительного одобрения!</b>\n\n\
                📋 <b>Заявка #{}</b>\n\
                ❌ <b>Ошибка:</b> {}\n\n\
                💡 <b>Примечание:</b> Даже принудительное одобрение не удалось. Обратитесь к разработчикам.",
                request_id, error_details),
            )
            .parse_mode(teloxide::types::ParseMode::Html)
            .reply_markup(make_inline_keyboard(
                vec![("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into()],
                1,
            ))
            .await?;
        }
        Err(api::WithdrawRequestError::Other { message }) => {
            log::error!("Failed to force approve withdraw request {}: {}", request_id, message);
            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!("❌ Ошибка при принудительном одобрении: {}", message),
            )
            .reply_markup(make_inline_keyboard(
                vec![("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into()],
                1,
            ))
            .await?;
        }
    }

    Ok(())
}

pub async fn handle_withdraw_request_action(
    bot: Bot,
    _dialogue: MasterDialogue,
    msg: Message,
    request_id: i64,
    action: &str,
) -> HandlerResult {
    let action_text = match action {
        "approved" => "одобрение",
        "rejected" => "отклонение", 
        "cancelled" => "отмена",
        _ => "обновление",
    };

    bot.edit_message_text(
        msg.chat.id,
        msg.id,
        format!("⏳ Выполняем {} заявки #{}...", action_text, request_id),
    )
    .await?;

    match api::update_withdraw_request_status(request_id, action.to_string(), false).await {
        Ok(()) => {
            let success_text = match action {
                "approved" => "одобрена",
                "rejected" => "отклонена",
                "cancelled" => "отменена",
                _ => "обновлена",
            };

            let success_emoji = match action {
                "approved" => "✅",
                "rejected" => "❌",
                "cancelled" => "🚫",
                _ => "✔️",
            };

            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!(
                    "{} <b>Заявка #{} успешно {}!</b>",
                    success_emoji,
                    request_id,
                    success_text,
                ),
            )
            .parse_mode(teloxide::types::ParseMode::Html)
            .reply_markup(make_inline_keyboard(
                vec![
                    ("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into(),
                    ("🏠 Главное меню", AdminCallback::AdminMenu).into()
                ],
                1,
            ))
            .await?;
        }
        Err(api::WithdrawRequestError::InsufficientBalance { request_id, error_details }) => {
            log::warn!("Insufficient balance for withdraw request {}: {}", request_id, error_details);
            
            let conflict_message = format!(
                "⚠️ <b>Недостаточно средств для вывода!</b>\n\n\
                📋 <b>Заявка #{}</b>\n\
                ❌ <b>Ошибка:</b> {}\n\n\
                💡 <b>Важно:</b> Принудительное одобрение приведет к <b>отрицательному балансу</b> пользователя!\n\n\
                Выберите действие:",
                request_id,
                error_details
            );

            let keyboard = make_inline_keyboard(
                vec![
                    ("⚠️ Принудительно одобрить", AdminCallback::WithdrawRequestForce { request_id }.to_string()).into(),
                    ("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu.to_string()).into(),
                ],
                1,
            );

            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                conflict_message,
            )
            .parse_mode(teloxide::types::ParseMode::Html)
            .reply_markup(keyboard)
            .await?;
        }
        Err(api::WithdrawRequestError::Other { message }) => {
            log::error!("Failed to update withdraw request {}: {}", request_id, message);
            bot.edit_message_text(
                msg.chat.id,
                msg.id,
                format!("❌ Ошибка при выполнении действия: {}", message),
            )
            .reply_markup(make_inline_keyboard(
                vec![("🔙 К списку заявок", AdminCallback::WithdrawRequestsMenu).into()],
                1,
            ))
            .await?;
        }
    }

    Ok(())
}