// Auto-generated by crates/tele-codegen. Do not edit manually.
use serde::Serialize;
use serde_json::Value;

use crate::{Error, Result};

use crate::types::validation::{
    non_negative_i64 as validate_non_negative_i64, positive_i64 as validate_positive_i64,
    required_string as validate_required_string, string_id as validate_string_id,
};

use super::AdvancedRequest;

trait GeneratedValidate {
    fn validate_generated(&self) -> Result<()>;
}

impl GeneratedValidate for crate::types::common::MessageId {
    fn validate_generated(&self) -> Result<()> {
        self.validate()
    }
}

impl GeneratedValidate for crate::types::telegram::InputPaidMedia {
    fn validate_generated(&self) -> Result<()> {
        self.validate()
    }
}

impl GeneratedValidate for crate::types::telegram::ReactionType {
    fn validate_generated(&self) -> Result<()> {
        self.validate()
    }
}

fn validate_items<T: GeneratedValidate>(values: &[T]) -> Result<()> {
    for value in values {
        value.validate_generated()?;
    }

    Ok(())
}

fn validate_required_items<T: GeneratedValidate>(field: &str, values: &[T]) -> Result<()> {
    if values.is_empty() {
        return Err(Error::InvalidRequest {
            reason: format!("{field} cannot be empty"),
        });
    }

    validate_items(values)
}

fn validate_message_ids(values: &[crate::types::common::MessageId]) -> Result<()> {
    for value in values {
        value.validate()?;
    }

    Ok(())
}

fn validate_required_message_ids(
    field: &str,
    values: &[crate::types::common::MessageId],
) -> Result<()> {
    if values.is_empty() {
        return Err(Error::InvalidRequest {
            reason: format!("{field} cannot be empty"),
        });
    }

    validate_message_ids(values)
}

/// Auto-generated request for `getMe`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedGetMeRequest {}

impl AdvancedGetMeRequest {
    pub fn new() -> Self {
        Self {}
    }
}

impl AdvancedRequest for AdvancedGetMeRequest {
    type Response = crate::types::bot::User;
    const METHOD: &'static str = "getMe";
}

/// Auto-generated request for `forwardMessages`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedForwardMessagesRequest {
    pub chat_id: crate::types::common::ChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_thread_id: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub direct_messages_topic_id: Option<i64>,
    pub from_chat_id: crate::types::common::ChatId,
    pub message_ids: Vec<crate::types::common::MessageId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_notification: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protect_content: Option<bool>,
}

impl AdvancedForwardMessagesRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        from_chat_id: impl Into<crate::types::common::ChatId>,
        message_ids: Vec<crate::types::common::MessageId>,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            message_thread_id: None,
            direct_messages_topic_id: None,
            from_chat_id: from_chat_id.into(),
            message_ids,
            disable_notification: None,
            protect_content: None,
        }
    }
}

impl AdvancedRequest for AdvancedForwardMessagesRequest {
    type Response = Vec<crate::types::message::MessageIdObject>;
    const METHOD: &'static str = "forwardMessages";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        if let Some(value) = self.message_thread_id {
            validate_positive_i64("message_thread_id", value)?;
        }
        if let Some(value) = self.direct_messages_topic_id {
            validate_positive_i64("direct_messages_topic_id", value)?;
        }
        self.from_chat_id.validate()?;
        validate_required_message_ids("message_ids", &self.message_ids)?;
        Ok(())
    }
}

/// Auto-generated request for `sendVideoNote`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSendVideoNoteRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub business_connection_id: Option<String>,
    pub chat_id: crate::types::common::ChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_thread_id: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub direct_messages_topic_id: Option<i64>,
    pub video_note: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub duration: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub length: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub thumbnail: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_notification: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protect_content: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_paid_broadcast: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_effect_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub suggested_post_parameters: Option<crate::types::telegram::SuggestedPostParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_parameters: Option<crate::types::telegram::ReplyParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::ReplyMarkup>,
}

impl AdvancedSendVideoNoteRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        video_note: impl Into<String>,
    ) -> Self {
        Self {
            business_connection_id: None,
            chat_id: chat_id.into(),
            message_thread_id: None,
            direct_messages_topic_id: None,
            video_note: video_note.into(),
            duration: None,
            length: None,
            thumbnail: None,
            disable_notification: None,
            protect_content: None,
            allow_paid_broadcast: None,
            message_effect_id: None,
            suggested_post_parameters: None,
            reply_parameters: None,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedSendVideoNoteRequest {
    type Response = crate::types::message::Message;
    const METHOD: &'static str = "sendVideoNote";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.business_connection_id.as_deref() {
            validate_string_id("business_connection_id", value)?;
        }
        self.chat_id.validate()?;
        if let Some(value) = self.message_thread_id {
            validate_positive_i64("message_thread_id", value)?;
        }
        if let Some(value) = self.direct_messages_topic_id {
            validate_positive_i64("direct_messages_topic_id", value)?;
        }
        validate_required_string("video_note", &self.video_note)?;
        if let Some(value) = self.duration {
            validate_positive_i64("duration", value)?;
        }
        if let Some(value) = self.length {
            validate_positive_i64("length", value)?;
        }
        if let Some(value) = self.message_effect_id.as_deref() {
            validate_string_id("message_effect_id", value)?;
        }
        if let Some(value) = self.suggested_post_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `sendPaidMedia`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSendPaidMediaRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub business_connection_id: Option<String>,
    pub chat_id: crate::types::common::ChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_thread_id: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub direct_messages_topic_id: Option<i64>,
    pub star_count: i64,
    pub media: Vec<crate::types::telegram::InputPaidMedia>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub payload: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub caption: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub parse_mode: Option<crate::types::common::ParseMode>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub caption_entities: Option<Vec<crate::types::message::MessageEntity>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub show_caption_above_media: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_notification: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protect_content: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_paid_broadcast: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub suggested_post_parameters: Option<crate::types::telegram::SuggestedPostParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_parameters: Option<crate::types::telegram::ReplyParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::ReplyMarkup>,
}

impl AdvancedSendPaidMediaRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        star_count: i64,
        media: Vec<crate::types::telegram::InputPaidMedia>,
    ) -> Self {
        Self {
            business_connection_id: None,
            chat_id: chat_id.into(),
            message_thread_id: None,
            direct_messages_topic_id: None,
            star_count,
            media,
            payload: None,
            caption: None,
            parse_mode: None,
            caption_entities: None,
            show_caption_above_media: None,
            disable_notification: None,
            protect_content: None,
            allow_paid_broadcast: None,
            suggested_post_parameters: None,
            reply_parameters: None,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedSendPaidMediaRequest {
    type Response = crate::types::message::Message;
    const METHOD: &'static str = "sendPaidMedia";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.business_connection_id.as_deref() {
            validate_string_id("business_connection_id", value)?;
        }
        self.chat_id.validate()?;
        if let Some(value) = self.message_thread_id {
            validate_positive_i64("message_thread_id", value)?;
        }
        if let Some(value) = self.direct_messages_topic_id {
            validate_positive_i64("direct_messages_topic_id", value)?;
        }
        validate_positive_i64("star_count", self.star_count)?;
        validate_required_items::<crate::types::telegram::InputPaidMedia>("media", &self.media)?;
        if let Some(value) = self.suggested_post_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `sendChecklist`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSendChecklistRequest {
    pub business_connection_id: String,
    pub chat_id: crate::types::common::NumericChatId,
    pub checklist: crate::types::telegram::InputChecklist,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_notification: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protect_content: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_effect_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_parameters: Option<crate::types::telegram::ReplyParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::InlineKeyboardMarkup>,
}

impl AdvancedSendChecklistRequest {
    pub fn new(
        business_connection_id: impl Into<String>,
        chat_id: impl Into<crate::types::common::NumericChatId>,
        checklist: crate::types::telegram::InputChecklist,
    ) -> Self {
        Self {
            business_connection_id: business_connection_id.into(),
            chat_id: chat_id.into(),
            checklist,
            disable_notification: None,
            protect_content: None,
            message_effect_id: None,
            reply_parameters: None,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedSendChecklistRequest {
    type Response = crate::types::message::Message;
    const METHOD: &'static str = "sendChecklist";

    fn validate(&self) -> Result<()> {
        validate_string_id("business_connection_id", &self.business_connection_id)?;
        self.chat_id.validate()?;
        self.checklist.validate()?;
        if let Some(value) = self.message_effect_id.as_deref() {
            validate_string_id("message_effect_id", value)?;
        }
        if let Some(value) = self.reply_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `sendMessageDraft`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSendMessageDraftRequest {
    pub chat_id: crate::types::common::NumericChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_thread_id: Option<i64>,
    pub draft_id: i64,
    pub text: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub parse_mode: Option<crate::types::common::ParseMode>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub entities: Option<Vec<crate::types::message::MessageEntity>>,
}

impl AdvancedSendMessageDraftRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::NumericChatId>,
        draft_id: i64,
        text: impl Into<String>,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            message_thread_id: None,
            draft_id,
            text: text.into(),
            parse_mode: None,
            entities: None,
        }
    }
}

impl AdvancedRequest for AdvancedSendMessageDraftRequest {
    type Response = bool;
    const METHOD: &'static str = "sendMessageDraft";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        if let Some(value) = self.message_thread_id {
            validate_positive_i64("message_thread_id", value)?;
        }
        validate_positive_i64("draft_id", self.draft_id)?;
        validate_required_string("text", &self.text)?;
        Ok(())
    }
}

/// Auto-generated request for `setMessageReaction`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSetMessageReactionRequest {
    pub chat_id: crate::types::common::ChatId,
    pub message_id: crate::types::common::MessageId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reaction: Option<Vec<crate::types::telegram::ReactionType>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub is_big: Option<bool>,
}

impl AdvancedSetMessageReactionRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        message_id: crate::types::common::MessageId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            message_id,
            reaction: None,
            is_big: None,
        }
    }
}

impl AdvancedRequest for AdvancedSetMessageReactionRequest {
    type Response = bool;
    const METHOD: &'static str = "setMessageReaction";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.message_id.validate()?;
        if let Some(values) = self.reaction.as_deref() {
            validate_items(values)?;
        }
        Ok(())
    }
}

/// Auto-generated request for `getUserProfileAudios`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedGetUserProfileAudiosRequest {
    pub user_id: crate::types::common::UserId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub offset: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
}

impl AdvancedGetUserProfileAudiosRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self {
            user_id,
            offset: None,
            limit: None,
        }
    }
}

impl AdvancedRequest for AdvancedGetUserProfileAudiosRequest {
    type Response = Value;
    const METHOD: &'static str = "getUserProfileAudios";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        if let Some(value) = self.offset {
            validate_non_negative_i64("offset", value)?;
        }
        if let Some(value) = self.limit {
            validate_positive_i64("limit", value)?;
        }
        Ok(())
    }
}

/// Auto-generated request for `setChatMemberTag`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSetChatMemberTagRequest {
    pub chat_id: crate::types::common::ChatId,
    pub user_id: crate::types::common::UserId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub tag: Option<String>,
}

impl AdvancedSetChatMemberTagRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        user_id: crate::types::common::UserId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            user_id,
            tag: None,
        }
    }
}

impl AdvancedRequest for AdvancedSetChatMemberTagRequest {
    type Response = bool;
    const METHOD: &'static str = "setChatMemberTag";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `createChatSubscriptionInviteLink`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedCreateChatSubscriptionInviteLinkRequest {
    pub chat_id: crate::types::common::ChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    pub subscription_period: i64,
    pub subscription_price: i64,
}

impl AdvancedCreateChatSubscriptionInviteLinkRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        subscription_period: i64,
        subscription_price: i64,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            name: None,
            subscription_period,
            subscription_price,
        }
    }
}

impl AdvancedRequest for AdvancedCreateChatSubscriptionInviteLinkRequest {
    type Response = crate::types::chat::ChatInviteLink;
    const METHOD: &'static str = "createChatSubscriptionInviteLink";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        validate_positive_i64("subscription_period", self.subscription_period)?;
        validate_positive_i64("subscription_price", self.subscription_price)?;
        Ok(())
    }
}

/// Auto-generated request for `editChatSubscriptionInviteLink`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedEditChatSubscriptionInviteLinkRequest {
    pub chat_id: crate::types::common::ChatId,
    pub invite_link: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

impl AdvancedEditChatSubscriptionInviteLinkRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        invite_link: impl Into<String>,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            invite_link: invite_link.into(),
            name: None,
        }
    }
}

impl AdvancedRequest for AdvancedEditChatSubscriptionInviteLinkRequest {
    type Response = crate::types::chat::ChatInviteLink;
    const METHOD: &'static str = "editChatSubscriptionInviteLink";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        validate_required_string("invite_link", &self.invite_link)?;
        Ok(())
    }
}

/// Auto-generated request for `approveChatJoinRequest`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedApproveChatJoinRequest {
    pub chat_id: crate::types::common::ChatId,
    pub user_id: crate::types::common::UserId,
}

impl AdvancedApproveChatJoinRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        user_id: crate::types::common::UserId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            user_id,
        }
    }
}

impl AdvancedRequest for AdvancedApproveChatJoinRequest {
    type Response = bool;
    const METHOD: &'static str = "approveChatJoinRequest";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `declineChatJoinRequest`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedDeclineChatJoinRequest {
    pub chat_id: crate::types::common::ChatId,
    pub user_id: crate::types::common::UserId,
}

impl AdvancedDeclineChatJoinRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        user_id: crate::types::common::UserId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            user_id,
        }
    }
}

impl AdvancedRequest for AdvancedDeclineChatJoinRequest {
    type Response = bool;
    const METHOD: &'static str = "declineChatJoinRequest";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `getUserChatBoosts`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedGetUserChatBoostsRequest {
    pub chat_id: crate::types::common::ChatId,
    pub user_id: crate::types::common::UserId,
}

impl AdvancedGetUserChatBoostsRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::ChatId>,
        user_id: crate::types::common::UserId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            user_id,
        }
    }
}

impl AdvancedRequest for AdvancedGetUserChatBoostsRequest {
    type Response = Value;
    const METHOD: &'static str = "getUserChatBoosts";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `getManagedBotToken`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedGetManagedBotTokenRequest {
    pub user_id: crate::types::common::UserId,
}

impl AdvancedGetManagedBotTokenRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self { user_id }
    }
}

impl AdvancedRequest for AdvancedGetManagedBotTokenRequest {
    type Response = String;
    const METHOD: &'static str = "getManagedBotToken";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `replaceManagedBotToken`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedReplaceManagedBotTokenRequest {
    pub user_id: crate::types::common::UserId,
}

impl AdvancedReplaceManagedBotTokenRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self { user_id }
    }
}

impl AdvancedRequest for AdvancedReplaceManagedBotTokenRequest {
    type Response = String;
    const METHOD: &'static str = "replaceManagedBotToken";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `setMyProfilePhoto`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSetMyProfilePhotoRequest {
    pub photo: crate::types::telegram::InputProfilePhoto,
}

impl AdvancedSetMyProfilePhotoRequest {
    pub fn new(photo: crate::types::telegram::InputProfilePhoto) -> Self {
        Self { photo }
    }
}

impl AdvancedRequest for AdvancedSetMyProfilePhotoRequest {
    type Response = bool;
    const METHOD: &'static str = "setMyProfilePhoto";

    fn validate(&self) -> Result<()> {
        self.photo.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `removeMyProfilePhoto`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedRemoveMyProfilePhotoRequest {}

impl AdvancedRemoveMyProfilePhotoRequest {
    pub fn new() -> Self {
        Self {}
    }
}

impl AdvancedRequest for AdvancedRemoveMyProfilePhotoRequest {
    type Response = bool;
    const METHOD: &'static str = "removeMyProfilePhoto";
}

/// Auto-generated request for `setChatMenuButton`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedSetChatMenuButtonRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub chat_id: Option<crate::types::common::NumericChatId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub menu_button: Option<crate::types::telegram::MenuButton>,
}

impl AdvancedSetChatMenuButtonRequest {
    pub fn new() -> Self {
        Self::default()
    }
}

impl AdvancedRequest for AdvancedSetChatMenuButtonRequest {
    type Response = bool;
    const METHOD: &'static str = "setChatMenuButton";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.chat_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.menu_button.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `getChatMenuButton`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedGetChatMenuButtonRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub chat_id: Option<crate::types::common::NumericChatId>,
}

impl AdvancedGetChatMenuButtonRequest {
    pub fn new() -> Self {
        Self::default()
    }
}

impl AdvancedRequest for AdvancedGetChatMenuButtonRequest {
    type Response = crate::types::telegram::MenuButton;
    const METHOD: &'static str = "getChatMenuButton";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.chat_id.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `setMyDefaultAdministratorRights`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedSetMyDefaultAdministratorRightsRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub rights: Option<crate::types::chat::ChatAdministratorRights>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub for_channels: Option<bool>,
}

impl AdvancedSetMyDefaultAdministratorRightsRequest {
    pub fn new() -> Self {
        Self::default()
    }
}

impl AdvancedRequest for AdvancedSetMyDefaultAdministratorRightsRequest {
    type Response = bool;
    const METHOD: &'static str = "setMyDefaultAdministratorRights";
}

/// Auto-generated request for `getMyDefaultAdministratorRights`.
#[derive(Clone, Debug, Default, Serialize)]
pub struct AdvancedGetMyDefaultAdministratorRightsRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub for_channels: Option<bool>,
}

impl AdvancedGetMyDefaultAdministratorRightsRequest {
    pub fn new() -> Self {
        Self::default()
    }
}

impl AdvancedRequest for AdvancedGetMyDefaultAdministratorRightsRequest {
    type Response = crate::types::chat::ChatAdministratorRights;
    const METHOD: &'static str = "getMyDefaultAdministratorRights";
}

/// Auto-generated request for `verifyUser`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedVerifyUserRequest {
    pub user_id: crate::types::common::UserId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub custom_description: Option<String>,
}

impl AdvancedVerifyUserRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self {
            user_id,
            custom_description: None,
        }
    }
}

impl AdvancedRequest for AdvancedVerifyUserRequest {
    type Response = bool;
    const METHOD: &'static str = "verifyUser";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `verifyChat`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedVerifyChatRequest {
    pub chat_id: crate::types::common::ChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub custom_description: Option<String>,
}

impl AdvancedVerifyChatRequest {
    pub fn new(chat_id: impl Into<crate::types::common::ChatId>) -> Self {
        Self {
            chat_id: chat_id.into(),
            custom_description: None,
        }
    }
}

impl AdvancedRequest for AdvancedVerifyChatRequest {
    type Response = bool;
    const METHOD: &'static str = "verifyChat";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `removeUserVerification`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedRemoveUserVerificationRequest {
    pub user_id: crate::types::common::UserId,
}

impl AdvancedRemoveUserVerificationRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self { user_id }
    }
}

impl AdvancedRequest for AdvancedRemoveUserVerificationRequest {
    type Response = bool;
    const METHOD: &'static str = "removeUserVerification";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `removeChatVerification`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedRemoveChatVerificationRequest {
    pub chat_id: crate::types::common::ChatId,
}

impl AdvancedRemoveChatVerificationRequest {
    pub fn new(chat_id: impl Into<crate::types::common::ChatId>) -> Self {
        Self {
            chat_id: chat_id.into(),
        }
    }
}

impl AdvancedRequest for AdvancedRemoveChatVerificationRequest {
    type Response = bool;
    const METHOD: &'static str = "removeChatVerification";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `answerWebAppQuery`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedAnswerWebAppQueryRequest {
    pub web_app_query_id: String,
    pub result: crate::types::telegram::InlineQueryResult,
}

impl AdvancedAnswerWebAppQueryRequest {
    pub fn new(
        web_app_query_id: impl Into<String>,
        result: crate::types::telegram::InlineQueryResult,
    ) -> Self {
        Self {
            web_app_query_id: web_app_query_id.into(),
            result,
        }
    }
}

impl AdvancedRequest for AdvancedAnswerWebAppQueryRequest {
    type Response = crate::types::message::SentWebAppMessage;
    const METHOD: &'static str = "answerWebAppQuery";

    fn validate(&self) -> Result<()> {
        validate_string_id("web_app_query_id", &self.web_app_query_id)?;
        self.result.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `savePreparedInlineMessage`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSavePreparedInlineMessageRequest {
    pub user_id: crate::types::common::UserId,
    pub result: crate::types::telegram::InlineQueryResult,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_user_chats: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_bot_chats: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_group_chats: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_channel_chats: Option<bool>,
}

impl AdvancedSavePreparedInlineMessageRequest {
    pub fn new(
        user_id: crate::types::common::UserId,
        result: crate::types::telegram::InlineQueryResult,
    ) -> Self {
        Self {
            user_id,
            result,
            allow_user_chats: None,
            allow_bot_chats: None,
            allow_group_chats: None,
            allow_channel_chats: None,
        }
    }
}

impl AdvancedRequest for AdvancedSavePreparedInlineMessageRequest {
    type Response = crate::types::message::Message;
    const METHOD: &'static str = "savePreparedInlineMessage";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        self.result.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `savePreparedKeyboardButton`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSavePreparedKeyboardButtonRequest {
    pub user_id: crate::types::common::UserId,
    pub button: crate::types::telegram::KeyboardButton,
}

impl AdvancedSavePreparedKeyboardButtonRequest {
    pub fn new(
        user_id: crate::types::common::UserId,
        button: crate::types::telegram::KeyboardButton,
    ) -> Self {
        Self { user_id, button }
    }
}

impl AdvancedRequest for AdvancedSavePreparedKeyboardButtonRequest {
    type Response = Value;
    const METHOD: &'static str = "savePreparedKeyboardButton";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        self.button.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `editMessageMedia`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedEditMessageMediaRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub business_connection_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub chat_id: Option<crate::types::common::ChatId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_id: Option<crate::types::common::MessageId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub inline_message_id: Option<String>,
    pub media: crate::types::message::InputMedia,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::InlineKeyboardMarkup>,
}

impl AdvancedEditMessageMediaRequest {
    pub fn new(media: crate::types::message::InputMedia) -> Self {
        Self {
            business_connection_id: None,
            chat_id: None,
            message_id: None,
            inline_message_id: None,
            media,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedEditMessageMediaRequest {
    type Response = crate::types::message::EditMessageResult;
    const METHOD: &'static str = "editMessageMedia";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.business_connection_id.as_deref() {
            validate_string_id("business_connection_id", value)?;
        }
        if let Some(value) = self.chat_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.message_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.inline_message_id.as_deref() {
            validate_string_id("inline_message_id", value)?;
        }
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `editMessageChecklist`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedEditMessageChecklistRequest {
    pub business_connection_id: String,
    pub chat_id: crate::types::common::NumericChatId,
    pub message_id: crate::types::common::MessageId,
    pub checklist: crate::types::telegram::InputChecklist,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::InlineKeyboardMarkup>,
}

impl AdvancedEditMessageChecklistRequest {
    pub fn new(
        business_connection_id: impl Into<String>,
        chat_id: impl Into<crate::types::common::NumericChatId>,
        message_id: crate::types::common::MessageId,
        checklist: crate::types::telegram::InputChecklist,
    ) -> Self {
        Self {
            business_connection_id: business_connection_id.into(),
            chat_id: chat_id.into(),
            message_id,
            checklist,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedEditMessageChecklistRequest {
    type Response = crate::types::message::Message;
    const METHOD: &'static str = "editMessageChecklist";

    fn validate(&self) -> Result<()> {
        validate_string_id("business_connection_id", &self.business_connection_id)?;
        self.chat_id.validate()?;
        self.message_id.validate()?;
        self.checklist.validate()?;
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `approveSuggestedPost`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedApproveSuggestedPostRequest {
    pub chat_id: crate::types::common::NumericChatId,
    pub message_id: crate::types::common::MessageId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub send_date: Option<i64>,
}

impl AdvancedApproveSuggestedPostRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::NumericChatId>,
        message_id: crate::types::common::MessageId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            message_id,
            send_date: None,
        }
    }
}

impl AdvancedRequest for AdvancedApproveSuggestedPostRequest {
    type Response = bool;
    const METHOD: &'static str = "approveSuggestedPost";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.message_id.validate()?;
        if let Some(value) = self.send_date {
            validate_positive_i64("send_date", value)?;
        }
        Ok(())
    }
}

/// Auto-generated request for `declineSuggestedPost`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedDeclineSuggestedPostRequest {
    pub chat_id: crate::types::common::NumericChatId,
    pub message_id: crate::types::common::MessageId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub comment: Option<String>,
}

impl AdvancedDeclineSuggestedPostRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::NumericChatId>,
        message_id: crate::types::common::MessageId,
    ) -> Self {
        Self {
            chat_id: chat_id.into(),
            message_id,
            comment: None,
        }
    }
}

impl AdvancedRequest for AdvancedDeclineSuggestedPostRequest {
    type Response = bool;
    const METHOD: &'static str = "declineSuggestedPost";

    fn validate(&self) -> Result<()> {
        self.chat_id.validate()?;
        self.message_id.validate()?;
        Ok(())
    }
}

/// Auto-generated request for `sendGame`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSendGameRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub business_connection_id: Option<String>,
    pub chat_id: crate::types::common::NumericChatId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_thread_id: Option<i64>,
    pub game_short_name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_notification: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub protect_content: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub allow_paid_broadcast: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_effect_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_parameters: Option<crate::types::telegram::ReplyParameters>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reply_markup: Option<crate::types::telegram::InlineKeyboardMarkup>,
}

impl AdvancedSendGameRequest {
    pub fn new(
        chat_id: impl Into<crate::types::common::NumericChatId>,
        game_short_name: impl Into<String>,
    ) -> Self {
        Self {
            business_connection_id: None,
            chat_id: chat_id.into(),
            message_thread_id: None,
            game_short_name: game_short_name.into(),
            disable_notification: None,
            protect_content: None,
            allow_paid_broadcast: None,
            message_effect_id: None,
            reply_parameters: None,
            reply_markup: None,
        }
    }
}

impl AdvancedRequest for AdvancedSendGameRequest {
    type Response = Value;
    const METHOD: &'static str = "sendGame";

    fn validate(&self) -> Result<()> {
        if let Some(value) = self.business_connection_id.as_deref() {
            validate_string_id("business_connection_id", value)?;
        }
        self.chat_id.validate()?;
        if let Some(value) = self.message_thread_id {
            validate_positive_i64("message_thread_id", value)?;
        }
        validate_required_string("game_short_name", &self.game_short_name)?;
        if let Some(value) = self.message_effect_id.as_deref() {
            validate_string_id("message_effect_id", value)?;
        }
        if let Some(value) = self.reply_parameters.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.reply_markup.as_ref() {
            value.validate()?;
        }
        Ok(())
    }
}

/// Auto-generated request for `setGameScore`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedSetGameScoreRequest {
    pub user_id: crate::types::common::UserId,
    pub score: i64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub force: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub disable_edit_message: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub chat_id: Option<crate::types::common::NumericChatId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_id: Option<crate::types::common::MessageId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub inline_message_id: Option<String>,
}

impl AdvancedSetGameScoreRequest {
    pub fn new(user_id: crate::types::common::UserId, score: i64) -> Self {
        Self {
            user_id,
            score,
            force: None,
            disable_edit_message: None,
            chat_id: None,
            message_id: None,
            inline_message_id: None,
        }
    }
}

impl AdvancedRequest for AdvancedSetGameScoreRequest {
    type Response = Value;
    const METHOD: &'static str = "setGameScore";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        validate_non_negative_i64("score", self.score)?;
        if let Some(value) = self.chat_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.message_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.inline_message_id.as_deref() {
            validate_string_id("inline_message_id", value)?;
        }
        Ok(())
    }
}

/// Auto-generated request for `getGameHighScores`.
#[derive(Clone, Debug, Serialize)]
pub struct AdvancedGetGameHighScoresRequest {
    pub user_id: crate::types::common::UserId,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub chat_id: Option<crate::types::common::NumericChatId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub message_id: Option<crate::types::common::MessageId>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub inline_message_id: Option<String>,
}

impl AdvancedGetGameHighScoresRequest {
    pub fn new(user_id: crate::types::common::UserId) -> Self {
        Self {
            user_id,
            chat_id: None,
            message_id: None,
            inline_message_id: None,
        }
    }
}

impl AdvancedRequest for AdvancedGetGameHighScoresRequest {
    type Response = Value;
    const METHOD: &'static str = "getGameHighScores";

    fn validate(&self) -> Result<()> {
        self.user_id.validate()?;
        if let Some(value) = self.chat_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.message_id.as_ref() {
            value.validate()?;
        }
        if let Some(value) = self.inline_message_id.as_deref() {
            validate_string_id("inline_message_id", value)?;
        }
        Ok(())
    }
}
