mod connection_handler;
mod namespace_handler;
mod resource_group_handler;
mod service_bus_handler;
mod subscription_handler;
pub use connection_handler::ConnectionHandler;
pub use namespace_handler::NamespaceHandler;
pub use resource_group_handler::ResourceGroupHandler;
pub use service_bus_handler::ServiceBusHandler;
pub use subscription_handler::SubscriptionHandler;
use crate::app::model::Model;
use crate::components::common::{AzureDiscoveryMsg, Msg};
use crate::error::AppError;
use tuirealm::terminal::TerminalAdapter;
impl<T> Model<T>
where
T: TerminalAdapter,
{
pub fn handle_subscription_selection(
&mut self,
msg: crate::components::common::SubscriptionSelectionMsg,
) -> Option<Msg> {
use crate::components::common::{ComponentId, SubscriptionSelectionMsg};
match msg {
SubscriptionSelectionMsg::SubscriptionSelected(subscription_id) => {
log::info!("Subscription selected: {subscription_id}");
self.state_manager.update_azure_selection(
Some(subscription_id.clone()),
None,
None,
);
if let Err(e) = self.app.umount(&ComponentId::SubscriptionPicker) {
log::error!("Failed to unmount subscription picker: {e}");
}
Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::DiscoveringResourceGroups(subscription_id),
))
}
SubscriptionSelectionMsg::CancelSelection => {
log::info!("Subscription selection cancelled - exiting application");
self.set_quit(true);
if let Err(e) = self.app.umount(&ComponentId::SubscriptionPicker) {
log::error!("Failed to unmount subscription picker: {e}");
}
Some(Msg::AppClose)
}
SubscriptionSelectionMsg::SelectionChanged => {
self.state_manager.set_redraw(true);
None
}
}
}
pub fn handle_resource_group_selection(
&mut self,
msg: crate::components::common::ResourceGroupSelectionMsg,
) -> Option<Msg> {
use crate::components::common::{ComponentId, ResourceGroupSelectionMsg};
match msg {
ResourceGroupSelectionMsg::ResourceGroupSelected(resource_group) => {
log::info!("Resource group selected: {resource_group}");
let subscription = self.state_manager.selected_subscription.clone();
if let Some(sub_id) = subscription.clone() {
self.state_manager.update_azure_selection(
Some(sub_id.clone()),
Some(resource_group),
None,
);
}
if let Err(e) = self.app.umount(&ComponentId::ResourceGroupPicker) {
log::error!("Failed to unmount resource group picker: {e}");
}
if let Some(subscription_id) = &subscription {
Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::DiscoveringNamespaces(subscription_id.clone()),
))
} else {
Some(Msg::AzureDiscovery(AzureDiscoveryMsg::DiscoveryError(
"No subscription selected".to_string(),
)))
}
}
ResourceGroupSelectionMsg::CancelSelection => {
log::info!("Resource group selection cancelled");
if let Err(e) = self.app.umount(&ComponentId::ResourceGroupPicker) {
log::error!("Failed to unmount resource group picker: {e}");
}
Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::DiscoveringSubscriptions,
))
}
ResourceGroupSelectionMsg::SelectionChanged => {
self.state_manager.set_redraw(true);
None
}
}
}
pub fn handle_azure_discovery(&mut self, msg: AzureDiscoveryMsg) -> Option<Msg> {
match msg {
AzureDiscoveryMsg::StartDiscovery => {
log::info!("Starting Azure resource discovery");
self.start_azure_discovery()
}
AzureDiscoveryMsg::StartInteractiveDiscovery => {
log::info!("Starting interactive Azure resource discovery");
self.start_interactive_discovery()
}
AzureDiscoveryMsg::DiscoveringSubscriptions => {
log::info!("Discovering Azure subscriptions");
SubscriptionHandler::discover(self)
}
AzureDiscoveryMsg::SubscriptionsDiscovered(subscriptions) => {
let count = subscriptions.len();
log::info!("Discovered {count} subscriptions");
SubscriptionHandler::handle_discovered(self, subscriptions)
}
AzureDiscoveryMsg::DiscoveringResourceGroups(subscription_id) => {
log::info!("Discovering resource groups for subscription: {subscription_id}");
ResourceGroupHandler::discover(self, subscription_id)
}
AzureDiscoveryMsg::ResourceGroupsDiscovered(groups) => {
let count = groups.len();
log::info!("Discovered {count} resource groups");
ResourceGroupHandler::handle_discovered(self, groups)
}
AzureDiscoveryMsg::DiscoveringNamespaces(subscription_id) => {
log::info!(
"Discovering Service Bus namespaces for subscription: {subscription_id}"
);
NamespaceHandler::discover(self, subscription_id)
}
AzureDiscoveryMsg::NamespacesDiscovered(namespaces) => {
let count = namespaces.len();
log::info!("Discovered {count} Service Bus namespaces");
NamespaceHandler::handle_discovered(self, namespaces)
}
AzureDiscoveryMsg::FetchingConnectionString {
subscription_id,
resource_group,
namespace,
} => {
log::info!("Fetching connection string for namespace: {namespace}");
ConnectionHandler::fetch(self, subscription_id, resource_group, namespace)
}
AzureDiscoveryMsg::ConnectionStringFetched(connection_string) => {
log::info!("Successfully fetched connection string");
ConnectionHandler::handle_fetched(self, connection_string)
}
AzureDiscoveryMsg::ServiceBusManagerCreated => {
log::info!("Service Bus manager created with discovered connection string");
ServiceBusHandler::handle_created(self)
}
AzureDiscoveryMsg::ServiceBusManagerReady(manager) => {
log::info!("Service Bus manager ready, storing it");
ServiceBusHandler::handle_ready(self, manager)
}
AzureDiscoveryMsg::DiscoveryError(error) => {
log::error!("Azure discovery error: {error}");
self.mount_error_popup(&AppError::ServiceBus(error))
.ok()
.map(|_| Msg::ForceRedraw)
}
AzureDiscoveryMsg::DiscoveryComplete => {
log::info!("Azure resource discovery completed");
self.finalize_discovery()
}
}
}
fn start_azure_discovery(&mut self) -> Option<Msg> {
self.state_manager.reset_azure_discovery_state();
if let Err(e) = crate::config::reload_config() {
log::warn!("Failed to reload configuration before discovery: {e}");
}
let config = crate::config::get_config_or_panic();
if config.servicebus().has_connection_string()
&& config.azure_ad().auth_method != "device_code"
{
log::info!(
"Connection string already configured and not using device code flow, skipping discovery"
);
return Some(Msg::AzureDiscovery(AzureDiscoveryMsg::DiscoveryComplete));
}
let azure_ad_config = config.azure_ad();
log::debug!("Checking Azure AD configuration completeness:");
log::debug!(
" has_subscription_id: {}",
azure_ad_config.has_subscription_id()
);
log::debug!(
" has_resource_group: {}",
azure_ad_config.has_resource_group()
);
log::debug!(" has_namespace: {}", azure_ad_config.has_namespace());
log::debug!(
" navigation_context: {:?}",
self.state_manager.navigation_context
);
if azure_ad_config.has_subscription_id()
&& azure_ad_config.has_resource_group()
&& azure_ad_config.has_namespace()
&& self.state_manager.should_auto_progress()
{
let subscription_id = azure_ad_config
.subscription_id()
.expect("subscription_id should be present");
let resource_group = azure_ad_config
.resource_group()
.expect("resource_group should be present");
let namespace = azure_ad_config
.namespace()
.expect("namespace should be present");
log::info!(
"Azure AD config complete and auto-progression enabled, skipping discovery and fetching connection string directly"
);
return Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::FetchingConnectionString {
subscription_id: subscription_id.to_string(),
resource_group: resource_group.to_string(),
namespace: namespace.to_string(),
},
));
}
log::info!("Azure AD config incomplete, starting discovery process");
Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::DiscoveringSubscriptions,
))
}
fn start_interactive_discovery(&mut self) -> Option<Msg> {
log::info!("Starting interactive discovery mode");
self.state_manager.start_discovery_mode();
log::info!("Resetting Azure discovery state to enable navigation");
self.state_manager.reset_azure_discovery_state();
Some(Msg::AzureDiscovery(
AzureDiscoveryMsg::DiscoveringSubscriptions,
))
}
fn finalize_discovery(&mut self) -> Option<Msg> {
log::info!("Finalizing Azure discovery");
self.state_manager.set_authentication_state(false);
if self.state_manager.discovered_connection_string.is_some() {
let _ = self
.app
.umount(&crate::components::common::ComponentId::SubscriptionPicker);
let _ = self
.app
.umount(&crate::components::common::ComponentId::ResourceGroupPicker);
let _ = self
.app
.umount(&crate::components::common::ComponentId::NamespacePicker);
log::info!("Discovery complete - ready for queue operations");
if let (
Some(subscription_id),
Some(resource_group),
Some(namespace),
Some(auth_service),
) = (
&self.state_manager.selected_subscription,
&self.state_manager.selected_resource_group,
&self.state_manager.selected_namespace,
&self.auth_service,
) {
log::info!("Loading queues for discovered namespace: {namespace}");
self.queue_manager.load_queues_with_discovery(
subscription_id.clone(),
resource_group.clone(),
namespace.clone(),
auth_service.clone(),
self.http_client.clone(),
);
}
}
None
}
}