use crate::{
    consts::stickers::*,
    errors::UserBotError,
    helpers::image,
    userbot::{CommandHandlerResult, UserBot},
    *,
};
use grammers_client::types::{Chat, InputMessage, Media, Message};
use grammers_mtproto::mtp::RpcError;
use grammers_mtsender::InvocationError;
use grammers_tl_types as tl;
use once_cell::sync::OnceCell;
use reusable_fmt::fmt;
use std::ops::Deref;
use tokio::sync::Mutex;
use unic_emoji_char::is_emoji;
static STICKER_CHAT: OnceCell<Mutex<Chat>> = OnceCell::new();
pub async fn get_sticker_handler(bot: &mut UserBot, message: &mut Message) -> CommandHandlerResult {
    let reply = bot
        .get_reply_to_message(message)
        .await
        .ok_or(UserBotError::NoArguments)?;
    let media = reply.media().ok_or(UserBotError::NoSticker)?;
    let sticker_file = match media {
        Media::Sticker(sticker) => sticker.document,
        Media::Document(document)
            if document
                .mime_type()
                .filter(|mime| matches!(*mime, "image/webp" | "image/png"))
                .is_some() =>
        {
            document
        }
        _ => Err(UserBotError::NoSticker)?,
    };
    let fname = sticker_file.name().to_string();
    let sticker_media = Media::Document(sticker_file);
    let dlbuf = bot.download_media(message, Some(sticker_media)).await?;
    let sticker = bot.upload_media(&dlbuf, fname).await?;
    message.reply(InputMessage::text("").file(sticker)).await?;
    Ok(())
}
async fn pack_exists(bot: &mut UserBot, pack: &str) -> Result<bool, InvocationError> {
    let stickerset = tl::types::InputStickerSetShortName {
        short_name: pack.to_string(),
    }
    .into();
    let req = tl::functions::messages::GetStickerSet {
        stickerset,
        hash: 0,
    };
    match bot.client.invoke(&req).await {
        Ok(_) => Ok(true),
        Err(InvocationError::Rpc(RpcError { ref name, .. })) if name == STICKERSET_INVALID => {
            Ok(false)
        }
        Err(e) => Err(e),
    }
}
pub async fn kang_handler(bot: &mut UserBot, message: &mut Message) -> CommandHandlerResult {
    let args = bot.get_args_nr(message, true);
    let reply = bot
        .get_reply_to_message(message)
        .await
        .ok_or(UserBotError::NoArguments)?;
    let mut emoji = DEFAULT_EMOJI.to_string();
    let mut resize = true;
    let media = reply.media().ok_or(UserBotError::NoArguments)?;
    let sticker = match &media {
        Media::Photo(_) => Ok(media),
        Media::Sticker(sticker) => {
            emoji = sticker.emoji().to_string();
            resize = false;
            Ok(media)
        }
        Media::Document(document)
            if document
                .mime_type()
                .filter(|mime| matches!(*mime, "image/webp" | "image/png" | "image/jpeg"))
                .is_some() =>
        {
            Ok(media)
        }
        _ => Err(UserBotError::NoArguments),
    }?;
    if let Ok(mut args) = args {
        emoji = args.remove(0);
        if !is_emoji(emoji.chars().next().unwrap()) {
            return Err(UserBotError::StrNotEmoji);
        }
    }
    let me = bot.client.get_me().await?;
    let pack_user = me.username().unwrap_or(ANON_USER);
    let pack = helpers::db::sticker_pack_name(&bot.db, bot.tg_id, pack_user).await?;
    let pack_title = fmt!(PACK_TITLE_FMT, user = pack_user);
    let mut sticker_message = InputMessage::text("");
    sticker_message = if resize {
        let stick_bytes = bot.download_media(&reply, Some(sticker)).await?;
        let im: Vec<u8> = tokio::task::spawn_blocking(move || {
            let im = image::image_from_buf(&stick_bytes)?;
            let im = image::im_resize_clamped(&im, 512, 512);
            image::png_encode(im)
        })
        .await
        .unwrap()?;
        let sticker = bot.upload_media(&im, STICKER_FILE).await?;
        sticker_message.document(sticker)
    } else {
        sticker_message.copy_media(&sticker)
    };
    let mut sticker_chat = STICKER_CHAT.get();
    if sticker_chat.is_none() {
        let chat = bot
            .client
            .resolve_username(STICKERS_USERNAME)
            .await?
            .ok_or(UserBotError::ChatNotFound)?;
        STICKER_CHAT.set(Mutex::new(chat)).unwrap();
        sticker_chat = STICKER_CHAT.get();
    }
    let chatg = sticker_chat.unwrap().lock().await;
    let chat: &Chat = chatg.deref();
    let mut prev = bot
        .client
        .send_message(chat, InputMessage::text("/cancel"))
        .await?;
    bot.wait_reply(chat, &prev).await?;
    if !pack_exists(bot, &pack).await? {
        message.edit(InputMessage::markdown(CREATING_PACK)).await?;
        prev = prev.respond(InputMessage::text("/newpack")).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text(pack_title)).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(sticker_message).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text(emoji)).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text("/publish")).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text("/skip")).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text(&pack)).await?;
        bot.wait_reply(chat, &prev).await?;
    } else {
        prev = prev.respond(InputMessage::text("/addsticker")).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text(&pack)).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(sticker_message).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text(emoji)).await?;
        bot.wait_reply(chat, &prev).await?;
        prev = prev.respond(InputMessage::text("/done")).await?;
        bot.wait_reply(chat, &prev).await?;
    }
    std::mem::drop(chatg);
    message
        .edit(InputMessage::markdown(fmt!(
            PACK_ADD_SUCCESS,
            pack_name = pack
        )))
        .await?;
    Ok(())
}