use crate::{ ChurchApiClient, ChurchCoreConfig, models::{NewSchedule, ScheduleUpdate, NewBulletin, BulletinUpdate, NewEvent, EventUpdate}, }; use tokio::runtime::Runtime; use std::sync::OnceLock; static CLIENT: OnceLock = OnceLock::new(); static RT: OnceLock = OnceLock::new(); fn get_client() -> &'static ChurchApiClient { CLIENT.get_or_init(|| { let config = ChurchCoreConfig::default(); ChurchApiClient::new(config).expect("Failed to create church client") }) } fn get_runtime() -> &'static Runtime { RT.get_or_init(|| { Runtime::new().expect("Failed to create async runtime") }) } // Configuration functions pub fn get_church_name() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.church_name.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_contact_phone() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.contact_phone.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_contact_email() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.contact_email.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_church_address() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.church_address.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_church_physical_address() -> String { get_church_address() } pub fn get_church_po_box() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.po_box.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_mission_statement() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.mission_statement.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_facebook_url() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.facebook_url.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_youtube_url() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.youtube_url.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_instagram_url() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => config.instagram_url.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } pub fn get_stream_live_status() -> bool { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_stream_status()) { Ok(status) => status.is_live, Err(_) => false, } } pub fn get_livestream_url() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_live_stream()) { Ok(stream) => stream.stream_title.unwrap_or_else(|| "".to_string()), Err(e) => format!("Error: {}", e), } } // JSON API functions pub fn fetch_events_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_upcoming_events(Some(50))) { Ok(events) => { // Format events with display formatting using existing Event methods let formatted_events: Vec<_> = events.iter().map(|event| { let mut event_json = serde_json::to_value(event).unwrap_or_default(); // Add formatted fields using Event's built-in methods if let Some(obj) = event_json.as_object_mut() { obj.insert("formatted_date".to_string(), serde_json::Value::String(event.formatted_date_range())); obj.insert("formatted_time".to_string(), serde_json::Value::String(event.formatted_start_time())); } event_json }).collect(); serde_json::to_string(&formatted_events).unwrap_or_else(|_| "[]".to_string()) }, Err(_) => "[]".to_string(), } } pub fn fetch_featured_events_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_featured_events_v2(Some(10))) { Ok(events) => serde_json::to_string(&events).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn fetch_sermons_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_recent_sermons(Some(20))) { Ok(sermons) => serde_json::to_string(&sermons).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn fetch_config_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_config()) { Ok(config) => serde_json::to_string(&config).unwrap_or_else(|_| "{}".to_string()), Err(_) => "{}".to_string(), } } pub fn fetch_random_bible_verse_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_random_verse()) { Ok(verse) => serde_json::to_string(&verse).unwrap_or_else(|_| "{}".to_string()), Err(_) => "{}".to_string(), } } pub fn fetch_bulletins_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_bulletins(true)) { Ok(bulletins) => serde_json::to_string(&bulletins).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn fetch_current_bulletin_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_current_bulletin()) { Ok(Some(bulletin)) => serde_json::to_string(&bulletin).unwrap_or_else(|_| "{}".to_string()), Ok(None) => "{}".to_string(), Err(_) => "{}".to_string(), } } pub fn fetch_bible_verse_json(query: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_verse_by_reference(&query)) { Ok(Some(verse)) => serde_json::to_string(&verse).unwrap_or_else(|_| "{}".to_string()), Ok(None) => "{}".to_string(), Err(_) => "{}".to_string(), } } pub fn fetch_livestream_archive_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_livestreams()) { Ok(streams) => serde_json::to_string(&streams).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn submit_contact_v2_json(name: String, email: String, subject: String, message: String, phone: String) -> String { let client = get_client(); let rt = get_runtime(); let contact = crate::models::ContactForm::new(name, email, subject, message) .with_phone(phone); match rt.block_on(client.submit_contact_form_v2(contact)) { Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn validate_contact_form_json(form_json: String) -> String { match serde_json::from_str::(&form_json) { Ok(_) => serde_json::to_string(&crate::utils::ValidationResult::valid()).unwrap_or_else(|_| "{}".to_string()), Err(_) => serde_json::to_string(&crate::utils::ValidationResult::invalid(vec!["Invalid JSON format".to_string()])).unwrap_or_else(|_| "{}".to_string()), } } pub fn submit_event_json( title: String, description: String, start_time: String, end_time: String, location: String, location_url: Option, category: String, recurring_type: Option, submitter_email: Option ) -> String { let client = get_client(); let rt = get_runtime(); let submission = crate::models::EventSubmission { title, description, start_time, end_time, location, location_url, category, recurring_type, submitter_email: submitter_email.unwrap_or_else(|| "".to_string()), is_featured: false, bulletin_week: None, image_data: None, image_filename: None, image_mime_type: None, }; match rt.block_on(client.submit_event(submission)) { Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn submit_event_with_image_json( title: String, description: String, start_time: String, end_time: String, location: String, location_url: Option, category: String, recurring_type: Option, submitter_email: Option, image_data: Option>, image_filename: Option ) -> String { let client = get_client(); let rt = get_runtime(); let submission = crate::models::EventSubmission { title, description, start_time, end_time, location, location_url, category, recurring_type, submitter_email: submitter_email.unwrap_or_else(|| "".to_string()), is_featured: false, bulletin_week: None, image_data: image_data.clone(), image_filename: image_filename.clone(), image_mime_type: None, // Could be improved to detect from filename or data }; // Convert image data to format expected by multipart method let image_multipart = if let (Some(data), Some(filename)) = (image_data, image_filename) { Some((data, filename)) } else { None }; match rt.block_on(crate::client::events::submit_event_with_image(client, submission, image_multipart)) { Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } // Admin functions pub fn fetch_all_schedules_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.get_all_admin_schedules()) { Ok(schedules) => serde_json::to_string(&schedules).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn create_schedule_json(schedule_json: String) -> String { let client = get_client(); let rt = get_runtime(); match serde_json::from_str::(&schedule_json) { Ok(schedule) => { match rt.block_on(client.create_admin_schedule(schedule)) { Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }, Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()), } } pub fn update_schedule_json(date: String, update_json: String) -> String { let client = get_client(); let rt = get_runtime(); match serde_json::from_str::(&update_json) { Ok(update) => { match rt.block_on(client.update_admin_schedule(&date, update)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }, Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()), } } pub fn delete_schedule_json(date: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.delete_admin_schedule(&date)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } // Admin Auth Functions pub fn admin_login_json(email: String, password: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.admin_login(&email, &password)) { Ok(token) => serde_json::to_string(&serde_json::json!({"success": true, "token": token})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn validate_admin_token_json(token: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(client.validate_admin_token(&token)) { Ok(valid) => serde_json::to_string(&serde_json::json!({"success": true, "valid": valid})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } // Admin Events Functions pub fn fetch_pending_events_json() -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::get_pending_events(client)) { Ok(events) => serde_json::to_string(&events).unwrap_or_else(|_| "[]".to_string()), Err(_) => "[]".to_string(), } } pub fn approve_pending_event_json(event_id: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::approve_pending_event(client, &event_id)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn reject_pending_event_json(event_id: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::reject_pending_event(client, &event_id)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn delete_pending_event_json(event_id: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::delete_pending_event(client, &event_id)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } pub fn update_admin_event_json(event_id: String, update_json: String) -> String { let client = get_client(); let rt = get_runtime(); match serde_json::from_str::(&update_json) { Ok(update) => { match rt.block_on(crate::client::admin::update_admin_event(client, &event_id, update)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }, Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()), } } pub fn delete_admin_event_json(event_id: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::delete_admin_event(client, &event_id)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } } // Admin Bulletins Functions pub fn create_bulletin_json(bulletin_json: String) -> String { let client = get_client(); let rt = get_runtime(); match serde_json::from_str::(&bulletin_json) { Ok(bulletin) => { match rt.block_on(crate::client::admin::create_bulletin(client, bulletin)) { Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }, Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()), } } pub fn update_bulletin_json(bulletin_id: String, update_json: String) -> String { let client = get_client(); let rt = get_runtime(); match serde_json::from_str::(&update_json) { Ok(update) => { match rt.block_on(crate::client::admin::update_bulletin(client, &bulletin_id, update)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }, Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()), } } pub fn delete_bulletin_json(bulletin_id: String) -> String { let client = get_client(); let rt = get_runtime(); match rt.block_on(crate::client::admin::delete_bulletin(client, &bulletin_id)) { Ok(_) => serde_json::to_string(&serde_json::json!({"success": true})).unwrap_or_else(|_| "{}".to_string()), Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()), } }