use crate::models::PluginID;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum LoginData {
    Direct(DirectLogin),
    OAuth(OAuthData),
    None(PluginID),
}

impl LoginData {
    pub fn id(&self) -> PluginID {
        match self {
            Self::OAuth(data) => data.id.clone(),
            Self::Direct(direct) => direct.id(),
            Self::None(id) => id.clone(),
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DirectLogin {
    Password(PasswordLogin),
    Token(TokenLogin),
}

impl DirectLogin {
    pub fn id(&self) -> PluginID {
        match self {
            Self::Password(data) => data.id.clone(),
            Self::Token(data) => data.id.clone(),
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TokenLogin {
    pub id: PluginID,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,
    pub token: String,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub basic_auth: Option<BasicAuth>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OAuthData {
    pub id: PluginID,
    pub url: String,
    pub custom_api_secret: Option<ApiSecret>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ApiSecret {
    pub client_id: String,
    pub client_secret: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PasswordLogin {
    pub id: PluginID,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<String>,
    pub user: String,
    pub password: String,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub basic_auth: Option<BasicAuth>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BasicAuth {
    pub user: String,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub password: Option<String>,
}
