use crate::authentication::IdentityProvider;
use async_trait::async_trait;
use http_api_isahc_client::IsahcClient;
use oauth2_client::re_exports::{ClientId, ClientSecret, RedirectUri};
use oauth2_gitlab::{GitlabExtensionsBuilder, GitlabProviderForEndUsers, GitlabScope, BASE_URL_GITLAB_COM};
use oauth2_signin::web_app::{SigninFlow, SigninFlowHandleCallbackByQueryConfiguration, SigninFlowHandleCallbackRet};

pub const GITLAB_BASE_URL: &str = "GITLAB_BASE_URL";

#[derive(Default)]
pub struct GitLabIdentityProvider {}

#[async_trait]
impl IdentityProvider for GitLabIdentityProvider {
    async fn handle_callback(
        &self,
        client_id: ClientId,
        client_secret: ClientSecret,
        redirect_uri: RedirectUri,
        query: impl AsRef<str> + Send,
    ) -> Result<SigninFlowHandleCallbackRet, Box<dyn std::error::Error>> {
        let client = IsahcClient::new()?;
        let base_url = std::env::var(GITLAB_BASE_URL).unwrap_or(BASE_URL_GITLAB_COM.to_string());
        let provider = GitlabProviderForEndUsers::new(base_url, client_id, client_secret, redirect_uri)?;
        let scopes = vec![GitlabScope::Email];
        let flow = SigninFlow::new(client, provider, scopes, GitlabExtensionsBuilder);
        let config = SigninFlowHandleCallbackByQueryConfiguration::new();
        Ok(flow.handle_callback_by_query(query, config).await)
    }
}
