use super::*;
use diesel::{
    prelude::*,
    result::{DatabaseErrorKind, Error as DieselError},
};
use internal::*;
use models::user::*;

#[command]
#[aliases("reg")]
#[description = "Register user"]
#[num_args(1)]
#[usage = "allycode"]
#[example = "123456789"]
pub fn register(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
    use schema::user::dsl::user;

    let ally_code: u64 = args.single::<u64>()?;

    debug!("command register with ally code {}", ally_code);

    // TODO find Swgoh username on swgoh.gg API
    let discord_username = String::from(&msg.author.name).replace(|c: char| !c.is_ascii(), "");

    let new_user = NewUser {
        discord_id: &msg.author.id.as_u64(),
        discord_username: &discord_username,
        swgoh_ally_code: &ally_code,
        swgoh_username: &ally_code.to_string(),
    };

    let conn = establish_connection();

    match diesel::insert_into(user).values(&new_user).execute(&conn) {
        Err(e) => Err(CommandError(handle_error(e, ally_code))),
        Ok(_) => {
            let msg_reply = MessageBuilder::new()
                .mention(&msg.author)
                .push(format!(", ally code '{}' registered!", ally_code))
                .build();

            if let Err(e) = msg.channel_id.say(&ctx, msg_reply) {
                error!("[E021] Error during send farming shards reply: {}", e);
            }
            Ok(())
        }
    }
}

fn handle_error(e: DieselError, ally_code: u64) -> String {
    debug!("{:?}", e);
    match e {
        DieselError::DatabaseError(kind, info) => match kind {
            DatabaseErrorKind::UniqueViolation => {
                let message = if info.message().contains("user_swgoh_ally_code_uindex") {
                    format!("Ally code '{}' is already used!", ally_code)
                } else if info.message().contains("user_discord_id_uindex") {
                    "You are already registered!".to_string()
                } else {
                    format!("{:?}", info)
                };

                error!("{}", message);

                message
            }
            _ => "<@409375902586372108> Internal error code 001, Unhandled kind".to_string(),
        },
        _ => "<@409375902586372108> Internal error code 002, Unhandled error".to_string(),
    }
}
