use chrono_tz::Tz;
use log::warn;
use poise::{CreateReply, Modal};
use serde::{Deserialize, Serialize};

use crate::{
    commands::autocomplete::{time_hint_autocomplete, timezone_autocomplete},
    models::reminder::create_reminder,
    utils::{Extract, Recordable},
    Context, Error,
};

#[derive(poise::Modal)]
#[name = "Reminder"]
struct ContentModal {
    #[name = "Content"]
    #[placeholder = "Message..."]
    #[paragraph]
    #[max_length = 2000]
    content: String,
}

#[derive(Serialize, Deserialize, Extract)]
pub struct Options {
    time: String,
    channels: Option<String>,
    interval: Option<String>,
    expires: Option<String>,
    tts: Option<bool>,
    timezone: Option<String>,
}

impl Recordable for Options {
    async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
        match ctx {
            Context::Application(app_ctx) => {
                let tz = self.timezone.map(|t| t.parse::<Tz>().ok()).flatten();
                let data_opt = ContentModal::execute(app_ctx).await?;

                match data_opt {
                    Some(data) => {
                        create_reminder(
                            ctx,
                            self.time,
                            data.content,
                            self.channels,
                            self.interval,
                            self.expires,
                            self.tts,
                            tz,
                        )
                        .await
                    }

                    None => {
                        warn!("Unexpected None encountered in /multiline");
                        Ok(ctx
                            .send(
                                CreateReply::default().content("Unexpected error.").ephemeral(true),
                            )
                            .await
                            .map(|_| ())?)
                    }
                }
            }

            _ => {
                warn!("Shouldn't be here");
                Ok(ctx
                    .send(CreateReply::default().content("Unexpected error.").ephemeral(true))
                    .await
                    .map(|_| ())?)
            }
        }
    }
}

/// Create a reminder with multi-line content. Press "+4 more" for other options.
#[poise::command(
    slash_command,
    rename = "multiline",
    identifying_name = "multiline",
    default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
    ctx: Context<'_>,
    #[description = "A description of the time to set the reminder for"]
    #[autocomplete = "time_hint_autocomplete"]
    time: String,
    #[description = "Channel or user mentions to set the reminder for"] channels: Option<String>,
    #[description = "(Patreon only) Time to wait before repeating the reminder. Leave blank for one-shot reminder"]
    interval: Option<String>,
    #[description = "(Patreon only) For repeating reminders, the time at which the reminder will stop repeating"]
    expires: Option<String>,
    #[description = "Set the TTS flag on the reminder message, similar to the /tts command"]
    tts: Option<bool>,
    #[description = "Set a timezone override for this reminder only"]
    #[autocomplete = "timezone_autocomplete"]
    timezone: Option<String>,
) -> Result<(), Error> {
    (Options { time, channels, interval, expires, tts, timezone }).run(ctx).await
}
