use serde::{Deserialize, Serialize};

use crate::{
    ids::{AuthProfileId, SecretId, WorkspaceId},
    protocol::AuthKind,
};

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BearerAuthConfig {
    pub header_name: String,
    pub secret_id: SecretId,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BasicAuthConfig {
    pub username_secret_id: SecretId,
    pub password_secret_id: SecretId,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ApiKeyHeaderAuthConfig {
    pub header_name: String,
    pub secret_id: SecretId,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ApiKeyQueryAuthConfig {
    pub param_name: String,
    pub secret_id: SecretId,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthConfig {
    Bearer(BearerAuthConfig),
    Basic(BasicAuthConfig),
    ApiKeyHeader(ApiKeyHeaderAuthConfig),
    ApiKeyQuery(ApiKeyQueryAuthConfig),
}

impl AuthConfig {
    pub fn secret_ids(&self) -> Vec<&SecretId> {
        match self {
            Self::Bearer(config) => vec![&config.secret_id],
            Self::Basic(config) => vec![&config.username_secret_id, &config.password_secret_id],
            Self::ApiKeyHeader(config) => vec![&config.secret_id],
            Self::ApiKeyQuery(config) => vec![&config.secret_id],
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthProfile {
    pub id: AuthProfileId,
    pub workspace_id: WorkspaceId,
    pub name: String,
    pub kind: AuthKind,
    pub config: AuthConfig,
    pub created_at: String,
    pub updated_at: String,
}
