use crate::prelude::*;
use std::sync::Arc;
use teloxide::{
    dispatching::{dialogue::GetChatId, DpHandlerDescription},
    dptree::Handler,
};

type DynError = Arc<dyn std::error::Error + Send + Sync>;

/// Filters out the messages from users without master passwords
///
/// # Returns
///
/// Returns None if account exists, Some(None) if there's an account and Some(Some(DynError)) if an error occures.
/// The String represents the error that occured
#[inline]
async fn master_pass_exists(update: Update, db: Pool) -> Option<Option<DynError>> {
    let user_id = match update.user() {
        Some(user) => user.id.0,
        None => return Some(Some(Arc::new(NoUserInfo))),
    };
    match MasterPass::exists(user_id, &db).await {
        Ok(true) => None,
        Ok(false) => Some(None),
        Err(err) => Some(Some(Arc::new(err))),
    }
}

#[inline]
async fn notify_about_no_master_pass(
    bot: Throttle<Bot>,
    result: Option<DynError>,
    update: Update,
) -> crate::Result<()> {
    if let Some(error) = result {
        return Err(error.into());
    }
    bot.send_message(
        update.chat_id().unwrap(),
        "No master password set. Use /set_master_pass to set it",
    )
    .reply_markup(deletion_markup())
    .await?;
    Ok(())
}

/// Gets a handler that filters out the messages of users that don't have a master password set
#[inline]
pub fn get_handler() -> Handler<'static, DependencyMap, crate::Result<()>, DpHandlerDescription> {
    dptree::filter_map_async(master_pass_exists).endpoint(notify_about_no_master_pass)
}