use dialoguer::{theme::ColorfulTheme, Select};
use graphql_client::GraphQLQuery;
use reqwest::Client;
use termimad::crossterm::style::Stylize;
use uuid::Uuid;
use crate::common::{
authorization_headers::authorization_headers, env_var::env_var,
execute_graphql_request::execute_graphql_request, print_formatted_error::print_formatted_error,
};
use crate::common::graphql::{
search_project_by_id::{search_project_by_id, SearchProjectById},
search_team_by_id::{search_team_by_id, SearchTeamById},
search_usage_history_by_id::{search_usage_history_by_id, SearchUsageHistoryById},
search_user_by_id::{search_user_by_id, SearchUserById},
search_user_secret_by_id::{search_user_secret_by_id, SearchUserSecretById},
};
pub enum QueryType {
Project,
UserSecret,
UsageHistory,
Teams,
User,
}
struct SelectItem {
id: Uuid,
description: String,
}
pub fn query_full_id(query_type: QueryType, short_id: String, access_token: &str) -> Uuid {
let min_id_length = match env_var("MIN_ID_LENGTH").parse() {
Ok(length) => length,
Err(_) => {
print_formatted_error("Fail parsing the number of minimum id length.");
std::process::exit(1);
}
};
let client = Client::new();
let authorization_headers = authorization_headers(access_token);
if short_id.len() < min_id_length {
print_formatted_error(&format!(
"The short ID should be at least {} characters long.",
min_id_length
));
std::process::exit(1);
}
let all_matches: Vec<SelectItem> = match query_type {
QueryType::Project => {
let project_error_message =
format!("Failed to retrieve project with ID '{}'.", &short_id);
let projects = execute_graphql_request::<
search_project_by_id::Variables,
search_project_by_id::ResponseData,
>(
authorization_headers.clone(),
SearchProjectById::build_query,
&client,
&project_error_message,
search_project_by_id::Variables {
id: short_id.clone(),
},
)
.search_project_by_id;
projects
.iter()
.map(|element| SelectItem {
id: element.id,
description: element.name.clone(),
})
.collect()
}
QueryType::UsageHistory => {
let usage_history_error_message =
format!("Failed to retrieve usage history with ID '{}'.", &short_id);
let usage_histories = execute_graphql_request::<
search_usage_history_by_id::Variables,
search_usage_history_by_id::ResponseData,
>(
authorization_headers.clone(),
SearchUsageHistoryById::build_query,
&client,
&usage_history_error_message,
search_usage_history_by_id::Variables {
id: short_id.clone(),
},
)
.search_usage_history_by_id;
usage_histories
.iter()
.map(|element| SelectItem {
id: element.id,
description: element
.created_at
.format(&env_var("DATE_FORMAT"))
.to_string(),
})
.collect()
}
QueryType::UserSecret => {
let user_secret_error_message =
format!("Failed to retrieve usage secret with ID '{}'.", &short_id);
let user_secrets = execute_graphql_request::<
search_user_secret_by_id::Variables,
search_user_secret_by_id::ResponseData,
>(
authorization_headers.clone(),
SearchUserSecretById::build_query,
&client,
&user_secret_error_message,
search_user_secret_by_id::Variables {
id: short_id.clone(),
},
)
.search_user_secret_by_id;
user_secrets
.iter()
.map(|element| SelectItem {
id: element.id,
description: element.name.clone(),
})
.collect()
}
QueryType::User => {
let user_error_message = format!("Failed to retrieve user with ID '{}'.", &short_id);
let users = execute_graphql_request::<
search_user_by_id::Variables,
search_user_by_id::ResponseData,
>(
authorization_headers.clone(),
SearchUserById::build_query,
&client,
&user_error_message,
search_user_by_id::Variables {
id: short_id.clone(),
},
)
.search_user_by_id;
users
.iter()
.map(|element| SelectItem {
id: element.id,
description: format!("{} ({})", element.name, element.email),
})
.collect()
}
QueryType::Teams => {
let team_error_message = format!("Failed to retrieve team with ID '{}'.", &short_id);
let teams = execute_graphql_request::<
search_team_by_id::Variables,
search_team_by_id::ResponseData,
>(
authorization_headers.clone(),
SearchTeamById::build_query,
&client,
&team_error_message,
search_team_by_id::Variables {
id: short_id.clone(),
},
)
.search_team_by_id;
teams
.iter()
.map(|element| SelectItem {
id: element.id,
description: element.name.clone(),
})
.collect()
}
};
match all_matches.len() {
0 => {
print_formatted_error("There is no such element.");
std::process::exit(1);
}
1 => all_matches[0].id,
_ => {
let items: Vec<String> = all_matches
.iter()
.map(|item| format!("{} {}", item.id.to_string().green(), item.description))
.collect();
let selected_item_index = match Select::with_theme(&ColorfulTheme::default())
.with_prompt("Select one:")
.default(0)
.items(&items)
.max_length(match env_var("ITEMS_PER_PAGE").parse::<usize>() {
Ok(max_length) => max_length,
Err(_) => {
print_formatted_error("Failed to parse ITEMS_PER_PAGE.");
std::process::exit(1);
}
})
.interact()
{
Ok(selected_index) => selected_index,
Err(_) => {
print_formatted_error("Failed to read items in the selection.");
std::process::exit(1);
}
};
all_matches[selected_item_index].id
}
}
}