use crate::domain::ports::notifier::Notifier;
use crate::domain::ports::repositories::ResourceUsageRepository;
use crate::interface::slack::app::SlackApp;
use crate::interface::slack::constants::*;
use crate::interface::slack::slack_client::modals;
use crate::interface::slack::views::modals::reserve;
use slack_morphism::prelude::*;
use tracing::{error, info};
pub async fn handle<R, N>(
app: &SlackApp<R, N>,
block_actions: &SlackInteractionBlockActionsEvent,
action: &SlackInteractionActionInfo,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
where
R: ResourceUsageRepository + Send + Sync + 'static,
N: Notifier + Send + Sync + 'static,
{
let action_id = action.action_id.to_string();
info!("🔄 モーダル更新トリガー検出: {}", action_id);
let config = app.resource_config();
let slack_client = app.slack_client();
let bot_token = app.bot_token();
let new_resource_type = if action_id == ACTION_RESERVE_RESOURCE_TYPE {
action
.selected_option
.as_ref()
.map(|opt| opt.value.as_str())
} else {
None
};
let new_selected_server = if action_id == ACTION_RESERVE_SERVER_SELECT {
action
.selected_option
.as_ref()
.map(|opt| opt.value.as_str())
} else if new_resource_type.is_some() && new_resource_type == Some("gpu") {
config.servers.first().map(|s| s.name.as_str())
} else {
None
};
let view_id = match &block_actions.container {
SlackInteractionActionContainer::View(view_container) => {
info!(
" → view_id取得成功: {}",
view_container.view_id.to_string()
);
view_container.view_id.clone()
}
SlackInteractionActionContainer::Message(_) => {
error!("❌ モーダル外のインタラクションです");
return Ok(());
}
};
info!(
"📝 選択値: type={:?}, server={:?}",
new_resource_type, new_selected_server
);
info!("🔨 新しいモーダルを作成中...");
let updated_modal = reserve::create_reserve_modal(
config,
new_resource_type,
new_selected_server,
None, None, None, None, );
info!("🚀 Slack APIにモーダル更新をリクエスト中...");
modals::update(slack_client, bot_token, &view_id, updated_modal).await?;
info!(
"✅ モーダルを動的に更新しました (view_id: {})",
view_id.to_string()
);
Ok(())
}