use super::{Context, Error};

use super::utils::serenity;

type Result = ::std::result::Result<(), Error>;

#[allow(clippy::unused_async)]
#[poise::command(
    slash_command,
    subcommands("add_channel", "list_channels", "remove_channel"),
    required_permissions = "ADMINISTRATOR"
)]
pub async fn logging(_ctx: Context<'_>) -> Result {
    Ok(())
}

#[poise::command(slash_command)]
pub async fn add_channel(
    ctx: Context<'_>,
    #[description = "New logging channel"] channel: serenity::Channel,
) -> Result {
    let channel_id = channel.id();
    let response = match ctx.guild_id() {
        None => "Error: Could not determine the guild's ID".to_owned(),
        Some(guild_id) => {
            match ctx
                .data()
                .database
                .set_logging_channel(guild_id, channel_id)
                .await
            {
                Ok(()) => format!(
                    "Added channel <#{channel_id}> as a logging channel"
                ),
                Err(e) => {
                    if let Some(db_error) = e.as_database_error() {
                        if db_error.is_unique_violation() {
                            format!("Channel <#{channel_id}> is already a logging channel")
                        } else {
                            format!("Error: {e:?}")
                        }
                    } else {
                        format!(
                            "Something bad happened with the database: {e:?}"
                        )
                    }
                }
            }
        }
    };
    ctx.say(response).await?;
    Ok(())
}

#[poise::command(slash_command)]
pub async fn list_channels(ctx: Context<'_>) -> Result {
    let response = match ctx.guild_id() {
        None => "Error: Could not determine the guild's ID".to_owned(),
        Some(guild_id) => {
            match ctx.data().database.get_logging_channel(guild_id).await {
                Err(e) => format!("Could not retrieve loggers: {e:?}"),
                Ok(channels) => {
                    if channels.is_empty() {
                        "No channels registered as loggers".to_owned()
                    } else {
                        format!(
                            "Here are the channels currently set as loggers:\n{}",
                            channels
                                .iter()
                                .map(|channel| format!("- <#{channel}>"))
                                .collect::<Vec<String>>()
                                .join("\n")
                        )
                    }
                }
            }
        }
    };
    ctx.say(response).await?;
    Ok(())
}

#[poise::command(slash_command)]
pub async fn remove_channel(
    ctx: Context<'_>,
    #[description = "Logger channel to remove"] channel: serenity::Channel,
) -> Result {
    let channel_id = channel.id();
    let response = match ctx.guild_id() {
        None => "Error: Could not determine the guild's ID".to_owned(),
        Some(guild_id) => {
            match ctx
                .data()
                .database
                .remove_logging_channel(guild_id, channel_id)
                .await
            {
                Ok(()) => {
                    format!("Removed channel <#{channel_id}> as a logger")
                }
                Err(e) => {
                    format!("Could not remove channel as a logger: {e:?}")
                }
            }
        }
    };
    ctx.say(response).await?;
    Ok(())
}