use chrono::prelude::Utc;
use models::farm_entry::NewFarmEntry;

use super::*;
use commands::unit::find_unit;

#[command]
#[aliases("sh")]
#[description = "Add a farm entry"]
#[usage = "unit shards [stars goals] [comment]"]
#[example = "vader 42/100 7 For solo rancor"]
pub fn shards(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
    use schema::farm_entry::dsl::farm_entry;

    let conn = establish_connection();

    let message = format!("user {} add {}", msg.author.id, args.rest());
    debug!("{}", message);

    let params: AddParams;
    match AddParams::parse(args, FarmType::Shard) {
        Ok(p) => params = p,
        Err(e) => {
            error!("{}", e);

            return if "end of string" == e.message {
                Err(CommandError("Missing some args".to_string()))
            } else {
                Err(CommandError(e.to_string()))
            };
        }
    }
    debug!("{:?}", params);

    let t = find_unit(&params.unit_name, &conn)?;
    let cu = get_current_user(msg.author.id.0)?;

    let mut farmed_unit = match get_farmed_unit(&cu, &t) {
        Some(ft) => ft,
        None => insert_farmed_unit(&cu, &t, &params, &conn, FarmType::Shard)?,
    };

    if params.goal_stars.is_some() && farmed_unit.stars_goal.unwrap() != params.goal_stars.unwrap()
    {
        farmed_unit.stars_goal = params.goal_stars;

        farmed_unit.save_changes::<UserFarm>(&conn).map_err(|e| {
            error!("Error during save: {}", e);
            CommandError(e.to_string())
        })?;
    }

    debug!("{:?}", farmed_unit);

    let new_farming = NewFarmEntry {
        comments: params.comments.as_ref(),
        current_shards: &params.current_shards,
        current_stars: &params.current_stars,
        date: &Utc::now().naive_utc(),
        user_farm_id: &farmed_unit.id,
    };

    match diesel::insert_into(farm_entry)
        .values(&new_farming)
        .execute(&conn)
    {
        Err(e) => Err(CommandError(handle_diesel_error(e, &t))),
        Ok(_) => {
            if let Err(e) = msg.channel_id.say(ctx, farmed_unit.print_current_summary()) {
                error!("[E021] Error during send farming shards reply: {}", e);
            }

            if let Some(e) = farmed_unit.get_last_entry() {
                farmed_unit.stars_finished =
                    0 == e.get_remaining_shards(farmed_unit.stars_goal.unwrap_or(7));

                farmed_unit.save_changes::<UserFarm>(&conn).map_err(|e| {
                    error!("Error during save: {}", e);
                    CommandError(e.to_string())
                })?;
            }

            Ok(())
        }
    }
}
