use diesel::prelude::*;
use internal::establish_connection;
use serenity::{
    framework::standard::{macros::command, Args, CommandError, CommandResult},
    model::{guild::Member, prelude::Message, user::User as DiscordUser},
    prelude::Context,
    Error,
};

use schema::user::dsl::discord_id as discord_id_dsl;
use schema::user::dsl::user as user_dsl;
use serenity::model::id::GuildId;

#[command]
#[aliases("nr")]
#[description = "List all not registered users from mentions"]
#[usage = "tag"]
#[example = "@members"]
pub fn not_registered(ctx: &mut Context, msg: &Message, mut _args: Args) -> CommandResult {
    let conn = establish_connection();

    let gid = msg.guild_id.unwrap();

    let users: Vec<u64> = user_dsl.select(discord_id_dsl).load::<u64>(&conn)?;

    let mut not_registered_users: Vec<String> = Vec::new();

    for mention in &msg.mentions {
        add_users(ctx, gid, &users, mention, &mut not_registered_users)
    }

    let members: Vec<Member> = gid.members(&ctx, Some(1000), None)?;
    for role in &msg.mention_roles {
        let has_role: Vec<DiscordUser> = members
            .iter()
            .filter(|m| m.user.read().has_role(&ctx, gid, role).unwrap())
            .map(|m| m.user_id().to_user(&ctx).unwrap())
            .collect();

        debug!("role: {}, users: {:?}", role, has_role);

        for user in &has_role {
            add_users(ctx, gid, &users, user, &mut not_registered_users)
        }
    }

    debug!("not registered: {:?}", not_registered_users);

    let mut reply = "".to_string();
    for unregistred_user in not_registered_users {
        reply.push_str(&format!("{}\n", unregistred_user));
    }

    msg.channel_id
        .say(
            &ctx,
            format!(
                "```asciidoc\nUser not registered:\n===================\n{}```",
                reply
            ),
        )
        .map_err(|e: Error| {
            error!("Error during reply: {}", e);
            CommandError(e.to_string())
        })?;

    Ok(())
}

fn add_users(
    ctx: &mut Context,
    gid: GuildId,
    users: &[u64],
    user: &DiscordUser,
    not_registered: &mut Vec<String>,
) {
    if !users.contains(&user.id.0) {
        not_registered.push(user.nick_in(&ctx, gid).unwrap_or_else(|| user.name.clone()));
    }
}
