use chrono::DateTime;
use serde::{Deserialize, Serialize};

use crate::{
    models::CtxData,
    time_parser::natural_parser,
    utils::{Extract, Recordable},
    Context, Error,
};

#[derive(Serialize, Deserialize, Extract)]
pub struct Options {
    until: Option<String>,
}

impl Recordable for Options {
    async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
        let timezone = ctx.timezone().await;

        let mut channel = ctx.channel_data().await.unwrap();

        match self.until {
            Some(until) => {
                let parsed = natural_parser(&until, &timezone.to_string()).await;

                if let Some(timestamp) = parsed {
                    match DateTime::from_timestamp(timestamp, 0) {
                        Some(dt) => {
                            channel.paused = true;
                            channel.paused_until = Some(dt.naive_utc());

                            channel.commit_changes(&ctx.data().database).await;

                            ctx.say(format!(
                                "Reminders in this channel have been silenced until **<t:{}:D>**",
                                timestamp
                            ))
                            .await?;
                        }

                        None => {
                            ctx.say(
                            "Time processed could not be interpreted as `DateTime`. Please write the time as clearly as possible",
                        )
                        .await?;
                        }
                    }
                } else {
                    ctx.say(
                        "Time could not be processed. Please write the time as clearly as possible",
                    )
                    .await?;
                }
            }
            _ => {
                channel.paused = !channel.paused;
                channel.paused_until = None;

                channel.commit_changes(&ctx.data().database).await;

                if channel.paused {
                    ctx.say("Reminders in this channel have been silenced indefinitely").await?;
                } else {
                    ctx.say("Reminders in this channel have been unsilenced").await?;
                }
            }
        }

        Ok(())
    }
}

/// Pause all reminders on the current channel until a certain time or indefinitely
#[poise::command(
    slash_command,
    rename = "pause",
    identifying_name = "pause",
    default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
    ctx: Context<'_>,
    #[description = "When to pause until"] until: Option<String>,
) -> Result<(), Error> {
    (Options { until }).run(ctx).await
}
