use crate::services::{bitrix24, redmine}; use askama::Template; use axum::Form; use axum::Json as AxumJson; use axum::response::{Html, IntoResponse, Json}; use serde::{Deserialize, Serialize}; use serde_json::json; use tower_sessions::Session; #[derive(Template)] #[template(path = "settings.html")] pub struct SettingsTemplate { pub redmine_url: String, pub redmine_user_id: String, pub bitrix_url: String, pub bitrix_webhook: String, pub error: Option, pub success: Option, } #[derive(Debug, Deserialize, Serialize, Clone)] pub struct UserSettings { pub redmine_url: String, pub redmine_api_key: String, pub redmine_user_id: u32, pub bitrix_url: String, pub bitrix_webhook: String, } #[derive(Debug, Deserialize)] pub struct SettingsForm { pub redmine_url: Option, pub redmine_api_key: Option, pub redmine_user_id: Option, pub bitrix_url: Option, pub bitrix_webhook: Option, } #[derive(Debug, Deserialize)] pub struct TestConnectionForm { pub redmine_url: Option, pub redmine_api_key: Option, pub redmine_user_id: Option, pub bitrix_url: Option, pub bitrix_webhook: Option, } pub async fn settings_page(session: Session) -> impl IntoResponse { let settings = session .get::("user_settings") .await .unwrap_or(None); let template = SettingsTemplate { redmine_url: settings .as_ref() .map(|s| s.redmine_url.clone()) .unwrap_or_default(), redmine_user_id: settings .as_ref() .map(|s| s.redmine_user_id.to_string()) .unwrap_or_default(), bitrix_url: settings .as_ref() .map(|s| s.bitrix_url.clone()) .unwrap_or_default(), bitrix_webhook: settings .as_ref() .map(|s| s.bitrix_webhook.clone()) .unwrap_or_default(), error: None, success: None, }; Html( template .render() .unwrap_or_else(|e| format!("Error: {}", e)), ) } pub async fn save_settings(session: Session, Form(form): Form) -> impl IntoResponse { let existing_settings = session .get::("user_settings") .await .unwrap_or(None); let redmine_url = if let Some(url) = form.redmine_url { if !url.is_empty() { url.trim().trim_matches('"').to_string() } else { existing_settings .as_ref() .map(|s| s.redmine_url.clone()) .unwrap_or_default() } } else { existing_settings .as_ref() .map(|s| s.redmine_url.clone()) .unwrap_or_default() }; let redmine_api_key = if let Some(key) = form.redmine_api_key { if !key.is_empty() { key } else { existing_settings .as_ref() .map(|s| s.redmine_api_key.clone()) .unwrap_or_default() } } else { existing_settings .as_ref() .map(|s| s.redmine_api_key.clone()) .unwrap_or_default() }; let redmine_user_id: u32 = if let Some(id_str) = form.redmine_user_id { if !id_str.is_empty() { match id_str.parse() { Ok(id) => id, Err(_) => { let template = SettingsTemplate { redmine_url: redmine_url.clone(), redmine_user_id: id_str, bitrix_url: form.bitrix_url.clone().unwrap_or_default(), bitrix_webhook: form.bitrix_webhook.clone().unwrap_or_default(), error: Some("User ID должен быть числом".to_string()), success: None, }; return Html( template .render() .unwrap_or_else(|e| format!("Error: {}", e)), ); } } } else { existing_settings .as_ref() .map(|s| s.redmine_user_id) .unwrap_or(0) } } else { existing_settings .as_ref() .map(|s| s.redmine_user_id) .unwrap_or(0) }; let bitrix_url = if let Some(url) = form.bitrix_url { if !url.is_empty() { url.trim().trim_matches('/').to_string() } else { existing_settings .as_ref() .map(|s| s.bitrix_url.clone()) .unwrap_or_default() } } else { existing_settings .as_ref() .map(|s| s.bitrix_url.clone()) .unwrap_or_default() }; let bitrix_webhook = if let Some(webhook) = form.bitrix_webhook { if !webhook.is_empty() { webhook.trim().trim_matches('/').to_string() } else { existing_settings .as_ref() .map(|s| s.bitrix_webhook.clone()) .unwrap_or_default() } } else { existing_settings .as_ref() .map(|s| s.bitrix_webhook.clone()) .unwrap_or_default() }; if redmine_url.is_empty() || redmine_api_key.is_empty() || redmine_user_id == 0 { let template = SettingsTemplate { redmine_url: redmine_url.clone(), redmine_user_id: redmine_user_id.to_string(), bitrix_url: bitrix_url.clone(), bitrix_webhook: bitrix_webhook.clone(), error: Some("Заполните все поля Redmine (URL, API Key, User ID)".to_string()), success: None, }; return Html( template .render() .unwrap_or_else(|e| format!("Error: {}", e)), ); } let settings = UserSettings { redmine_url: redmine_url.clone(), redmine_api_key, redmine_user_id, bitrix_url: bitrix_url.clone(), bitrix_webhook: bitrix_webhook.clone(), }; if let Err(e) = session.insert("user_settings", settings.clone()).await { let template = SettingsTemplate { redmine_url, redmine_user_id: redmine_user_id.to_string(), bitrix_url, bitrix_webhook, error: Some(format!("Ошибка сохранения: {}", e)), success: None, }; return Html( template .render() .unwrap_or_else(|e| format!("Error: {}", e)), ); } let template = SettingsTemplate { redmine_url: settings.redmine_url, redmine_user_id: settings.redmine_user_id.to_string(), bitrix_url: settings.bitrix_url, bitrix_webhook: settings.bitrix_webhook, error: None, success: Some("Настройки сохранены! Теперь можно загружать задачи.".to_string()), }; Html( template .render() .unwrap_or_else(|e| format!("Error: {}", e)), ) } pub async fn test_redmine_connection( session: Session, _form: AxumJson, ) -> impl IntoResponse { let settings = match session .get::("user_settings") .await .unwrap_or(None) { Some(s) => s, None => { return Json(json!({ "success": false, "message": "Сначала сохраните настройки" })); } }; match redmine::test_connection( &settings.redmine_api_key, &settings.redmine_url, settings.redmine_user_id, ) .await { Ok(count) => Json(json!({ "success": true, "message": format!("Подключение успешно! Найдено задач: {}", count), "count": count })), Err(e) => Json(json!({ "success": false, "message": format!("Ошибка: {}", e) })), } } pub async fn test_bitrix_connection( session: Session, _form: AxumJson, ) -> impl IntoResponse { let settings = match session .get::("user_settings") .await .unwrap_or(None) { Some(s) => s, None => { return Json(json!({ "success": false, "message": "Сначала сохраните настройки" })); } }; if settings.bitrix_url.is_empty() || settings.bitrix_webhook.is_empty() { return Json(json!({ "success": false, "message": "Заполните настройки Bitrix24" })); } match bitrix24::test_connection(&settings.bitrix_url, &settings.bitrix_webhook).await { Ok(info) => { let portal_name = info .portal_name .clone() .unwrap_or_else(|| "Bitrix24".to_string()); Json(json!({ "success": true, "message": format!("Подключение успешно! Портал: {}", portal_name), "info": info })) } Err(e) => Json(json!({ "success": false, "message": format!("Ошибка: {}", e) })), } }