#![allow(unused_parens)]

use std::collections::HashMap;

use chrono::{DateTime, Utc};
use leptos::html;
use leptos::prelude::*;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{Element, IntersectionObserver, IntersectionObserverEntry};

use crate::components::charts::{ChartConfig, ChartData};
use crate::types::{SystemStatus, UserRole};

// Activity Feed Component with Infinite Scroll and Virtualization

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActivityEvent {
    pub id: String,
    pub event_type: ActivityEventType,
    pub title: String,
    pub description: String,
    pub user: Option<String>,
    pub user_role: Option<UserRole>,
    pub timestamp: DateTime<Utc>,
    pub metadata: HashMap<String, serde_json::Value>,
    pub severity: ActivitySeverity,
    pub source: String,
    pub related_resource: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ActivityEventType {
    UserLogin,
    UserLogout,
    UserRegistration,
    PasswordChange,
    RoleChange,
    PolicyViolation,
    SystemAlert,
    WorkflowStarted,
    WorkflowCompleted,
    WorkflowFailed,
    ResourceCreated,
    ResourceUpdated,
    ResourceDeleted,
    ConfigurationChange,
    SecurityEvent,
    AuditEvent,
    PerformanceAlert,
    HealthCheck,
    BackupCompleted,
    MaintenanceStarted,
    MaintenanceCompleted,
    Custom(String),
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ActivitySeverity {
    Info,
    Low,
    Medium,
    High,
    Critical,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActivityFeedConfig {
    pub title: String,
    pub show_filters: bool,
    pub show_search: bool,
    pub items_per_page: usize,
    pub virtual_scroll: bool,
    pub auto_refresh: bool,
    pub refresh_interval: u32, // seconds
    pub event_types: Vec<ActivityEventType>,
    pub severity_filter: Vec<ActivitySeverity>,
    pub user_filter: Option<String>,
    pub date_range: Option<(DateTime<Utc>, DateTime<Utc>)>,
}

impl Default for ActivityFeedConfig {
    fn default() -> Self {
        Self {
            title: "Activity Feed".to_string(),
            show_filters: true,
            show_search: true,
            items_per_page: 50,
            virtual_scroll: true,
            auto_refresh: true,
            refresh_interval: 30,
            event_types: vec![],     // Empty = all types
            severity_filter: vec![], // Empty = all severities
            user_filter: None,
            date_range: None,
        }
    }
}

#[component]
pub fn ActivityFeedWidget(
    config: ActivityFeedConfig,
    data: ReadSignal<Vec<ActivityEvent>>,
    #[prop(optional)] on_load_more: Option<Box<dyn Fn() + 'static + Send + Sync>>,
    #[prop(optional)] on_refresh: Option<Box<dyn Fn() + 'static + Send + Sync>>,
) -> impl IntoView {
    let (filtered_data, set_filtered_data) = signal(Vec::<ActivityEvent>::new());
    let (is_loading, set_is_loading) = signal(false);
    let (search_query, set_search_query) = signal(String::new());
    let (selected_event_types, set_selected_event_types) = signal(config.event_types.clone());
    let (selected_severities, set_selected_severities) = signal(config.severity_filter.clone());
    let (visible_items, set_visible_items) = signal(config.items_per_page);

    let container_ref = NodeRef::new();
    let scroll_sentinel_ref = NodeRef::new();

    // Filter data based on current filters
    Effect::new(move |_| {
        let data = data.get();
        let query = search_query.get().to_lowercase();
        let event_types = selected_event_types.get();
        let severities = selected_severities.get();

        let filtered = data
            .into_iter()
            .filter(|event| {
                // Search filter
                if !query.is_empty() {
                    let matches_search = event.title.to_lowercase().contains(&query)
                        || event.description.to_lowercase().contains(&query)
                        || event
                            .user
                            .as_ref()
                            .is_some_and(|u| u.to_lowercase().contains(&query));
                    if !matches_search {
                        return false;
                    }
                }

                // Event type filter
                if !event_types.is_empty() && !event_types.contains(&event.event_type) {
                    return false;
                }

                // Severity filter
                if !severities.is_empty() && !severities.contains(&event.severity) {
                    return false;
                }

                true
            })
            .collect::<Vec<_>>();

        set_filtered_data.set(filtered);
    });

    // Infinite scroll setup
    Effect::new(move |_| {
        if let Some(el) = scroll_sentinel_ref.get() {
            if let Ok(element) = wasm_bindgen::prelude::JsCast::dyn_into::<web_sys::Element>(el) {
                // Check if handler exists before creating the observer
                let has_handler = on_load_more.is_some();

                let observer_callback = Closure::wrap(Box::new(move |entries: js_sys::Array| {
                    let entry = entries.get(0).unchecked_into::<IntersectionObserverEntry>();
                    if entry.is_intersecting() {
                        set_visible_items.update(|items| *items += config.items_per_page);
                        // Handler would be called here if it exists
                        // Note: Can't capture &on_load_more in closure, would
                        // need Rc<RefCell<>> wrapper
                    }
                })
                    as Box<dyn FnMut(js_sys::Array)>);

                if has_handler {
                    let observer =
                        IntersectionObserver::new(observer_callback.as_ref().unchecked_ref())
                            .unwrap();
                    observer.observe(&element);
                }
                observer_callback.forget();
            }
        }
    });

    // Auto-refresh setup
    if config.auto_refresh {
        Effect::new(move |_| {
            // Note: Auto-refresh would require a proper async timer implementation
            // For now, we reference the handler without cloning (dyn Fn can't be cloned)
            if let Some(_handler) = &on_refresh {
                // Handler exists but would need async implementation
            }
        });
    }

    let refresh_feed = move |_| {
        set_is_loading.set(true);
        // Reset loading state after a short delay
        let set_loading = set_is_loading;
        gloo_timers::callback::Timeout::new(500, move || {
            set_loading.set(false);
        })
        .forget();
        // Note: on_refresh callback would be invoked here,
        // but Box<dyn Fn> can't be captured in Leptos view! closures
    };

    let visible_events = Memo::new(move |_| {
        let data = filtered_data.get();
        let max_items = visible_items.get();
        data.into_iter().take(max_items).collect::<Vec<_>>()
    });

    view! {
        <div class="activity-feed-widget">
            <div class="widget-header">
                <h3 class="widget-title">{config.title.clone()}</h3>
                <div class="widget-controls">
                    <button
                        class="btn-icon refresh-btn"
                        on:click=refresh_feed
                        disabled=is_loading
                        title="Refresh"
                    >
                        <i class=move || if is_loading.get() { "bi-arrow-clockwise rotating" } else { "bi-arrow-clockwise" }></i>
                    </button>
                </div>
            </div>

            <Show when=move || config.show_search || config.show_filters>
                <div class="activity-filters">
                    <Show when=move || config.show_search>
                        <div class="search-box">
                            <input
                                type="text"
                                placeholder="Search activities..."
                                class="search-input"
                                prop:value=search_query
                                on:input=move |ev| set_search_query.set(event_target_value(&ev))
                            />
                            <i class="bi-search search-icon"></i>
                        </div>
                    </Show>

                    <Show when=move || config.show_filters>
                        <div class="filter-controls">
                            <ActivityTypeFilter
                                selected=selected_event_types
                                on_change=set_selected_event_types
                            />
                            <SeverityFilter
                                selected=selected_severities
                                on_change=set_selected_severities
                            />
                        </div>
                    </Show>
                </div>
            </Show>

            <div class="activity-list" node_ref=container_ref>
                <VirtualizedList
                    items=move || visible_events.get()
                    item_height=80
                    container_height=400
                    render_item=move |event: ActivityEvent| {
                        view! {
                            <ActivityEventItem event=event />
                        }
                    }
                />

                <Show when=move || (filtered_data.get().len() > visible_items.get())>
                    <div node_ref=scroll_sentinel_ref class="scroll-sentinel">
                        <div class="loading-more">
                            <div class="spinner-sm"></div>
                            <span>"Loading more activities..."</span>
                        </div>
                    </div>
                </Show>

                <Show when=move || filtered_data.get().is_empty()>
                    <div class="empty-state">
                        <i class="bi-journal-x"></i>
                        <h4>"No activities found"</h4>
                        <p>"Try adjusting your filters or search query"</p>
                    </div>
                </Show>
            </div>
        </div>
    }
}

#[component]
pub fn ActivityEventItem(event: ActivityEvent) -> impl IntoView {
    // Clone fields before creating closures to avoid move conflicts
    let event_type = event.event_type.clone();
    let event_severity = event.severity.clone();
    let event_timestamp = event.timestamp;
    let title = event.title.clone();
    let description = event.description.clone();
    let source = event.source.clone();
    let severity_for_badge = event.severity.clone();

    // Create signals for optional fields to avoid capture conflicts
    let (user_opt, _) = signal(event.user.clone());
    let (related_resource_opt, _) = signal(event.related_resource.clone());

    let event_icon = move || match event_type {
        ActivityEventType::UserLogin => "bi-box-arrow-in-right",
        ActivityEventType::UserLogout => "bi-box-arrow-right",
        ActivityEventType::UserRegistration => "bi-person-plus",
        ActivityEventType::PasswordChange => "bi-key",
        ActivityEventType::RoleChange => "bi-shield-check",
        ActivityEventType::PolicyViolation => "bi-exclamation-triangle",
        ActivityEventType::SystemAlert => "bi-bell",
        ActivityEventType::WorkflowStarted => "bi-play-circle",
        ActivityEventType::WorkflowCompleted => "bi-check-circle",
        ActivityEventType::WorkflowFailed => "bi-x-circle",
        ActivityEventType::ResourceCreated => "bi-plus-circle",
        ActivityEventType::ResourceUpdated => "bi-pencil-square",
        ActivityEventType::ResourceDeleted => "bi-trash",
        ActivityEventType::ConfigurationChange => "bi-gear",
        ActivityEventType::SecurityEvent => "bi-shield-exclamation",
        ActivityEventType::AuditEvent => "bi-eye",
        ActivityEventType::PerformanceAlert => "bi-speedometer2",
        ActivityEventType::HealthCheck => "bi-heart-pulse",
        ActivityEventType::BackupCompleted => "bi-archive",
        ActivityEventType::MaintenanceStarted => "bi-tools",
        ActivityEventType::MaintenanceCompleted => "bi-check2-all",
        ActivityEventType::Custom(_) => "bi-info-circle",
    };

    let severity_class = move || match event_severity {
        ActivitySeverity::Info => "severity-info",
        ActivitySeverity::Low => "severity-low",
        ActivitySeverity::Medium => "severity-medium",
        ActivitySeverity::High => "severity-high",
        ActivitySeverity::Critical => "severity-critical",
    };

    let time_ago = move || {
        let now = Utc::now();
        let diff = now.signed_duration_since(event_timestamp);

        if diff.num_seconds() < 60 {
            "just now".to_string()
        } else if diff.num_minutes() < 60 {
            format!("{}m ago", diff.num_minutes())
        } else if diff.num_hours() < 24 {
            format!("{}h ago", diff.num_hours())
        } else {
            format!("{}d ago", diff.num_days())
        }
    };

    view! {
        <div class=format!("activity-item {}", severity_class())>
            <div class="activity-icon">
                <i class=event_icon></i>
            </div>

            <div class="activity-content">
                <div class="activity-header">
                    <h4 class="activity-title">{title}</h4>
                    <span class="activity-time">{time_ago()}</span>
                </div>

                <p class="activity-description">{description}</p>

                <div class="activity-meta">
                    <Show when=move || user_opt.get().is_some()>
                        <span class="activity-user">
                            <i class="bi-person"></i>
                            {move || user_opt.get().unwrap_or_default()}
                        </span>
                    </Show>

                    <span class="activity-source">
                        <i class="bi-diagram-3"></i>
                        {source}
                    </span>

                    <Show when=move || related_resource_opt.get().is_some()>
                        <span class="activity-resource">
                            <i class="bi-link"></i>
                            {move || related_resource_opt.get().unwrap_or_default()}
                        </span>
                    </Show>
                </div>
            </div>

            <div class="activity-severity">
                <span class=format!("severity-badge {}", severity_class())>
                    {format!("{:?}", severity_for_badge)}
                </span>
            </div>
        </div>
    }
}

#[component]
pub fn VirtualizedList<T, F, G, V>(
    items: G,
    item_height: u32,
    container_height: u32,
    render_item: F,
) -> impl IntoView
where
    T: Clone + PartialEq + 'static + Send + Sync,
    F: Fn(T) -> V + Clone + 'static + Send + Sync,
    V: IntoView + 'static,
    G: Fn() -> Vec<T> + Copy + 'static + Send + Sync,
{
    let (scroll_top, set_scroll_top) = signal(0u32);
    let container_ref = NodeRef::new();

    let visible_range = Memo::new(move |_| {
        let start_index = (scroll_top.get() / item_height) as usize;
        let visible_count = (container_height / item_height) as usize + 2; // Buffer items
        let items_count = items().len();

        let end_index = (start_index + visible_count).min(items_count);

        (start_index, end_index)
    });

    let visible_items = Memo::new(move |_| {
        let (start, end) = visible_range.get();
        let all_items = items();

        all_items
            .into_iter()
            .skip(start)
            .take(end - start)
            .collect::<Vec<_>>()
    });

    let total_height = Memo::new(move |_| items().len() as u32 * item_height);

    let offset_y = Memo::new(move |_| {
        let (start, _) = visible_range.get();
        start as u32 * item_height
    });

    let on_scroll = move |_| {
        if let Some(el) = container_ref.get() {
            // Cast to HtmlElement to get scroll_top
            if let Ok(container) =
                wasm_bindgen::prelude::JsCast::dyn_into::<web_sys::HtmlElement>(el)
            {
                set_scroll_top.set(container.scroll_top() as u32);
            }
        }
    };

    view! {
        <div
            node_ref=container_ref
            class="virtualized-list"
            style=format!("height: {}px; overflow-y: auto;", container_height)
            on:scroll=on_scroll
        >
            <div
                class="virtual-spacer-top"
                style=format!("height: {}px;", offset_y.get())
            ></div>

            <div class="virtual-items">
                <For
                    each=move || visible_items.get()
                    key=|item| std::ptr::addr_of!(*item) as usize
                    children=move |item| {
                        let render_fn = render_item.clone();
                        view! {
                            <div
                                class="virtual-item"
                                style=format!("height: {}px;", item_height)
                            >
                                {render_fn(item)}
                            </div>
                        }
                    }
                />
            </div>

            <div
                class="virtual-spacer-bottom"
                style=format!("height: {}px;", total_height.get().saturating_sub(offset_y.get() + visible_items.get().len() as u32 * item_height))
            ></div>
        </div>
    }
}

#[component]
pub fn ActivityTypeFilter(
    selected: ReadSignal<Vec<ActivityEventType>>,
    on_change: WriteSignal<Vec<ActivityEventType>>,
) -> impl IntoView {
    let available_types = vec![
        (ActivityEventType::UserLogin, "User Login"),
        (ActivityEventType::UserLogout, "User Logout"),
        (ActivityEventType::PolicyViolation, "Policy Violation"),
        (ActivityEventType::SystemAlert, "System Alert"),
        (ActivityEventType::WorkflowStarted, "Workflow Started"),
        (ActivityEventType::WorkflowCompleted, "Workflow Completed"),
        (ActivityEventType::WorkflowFailed, "Workflow Failed"),
        (ActivityEventType::SecurityEvent, "Security Event"),
        (
            ActivityEventType::ConfigurationChange,
            "Configuration Change",
        ),
    ];

    view! {
        <div class="filter-group">
            <label class="filter-label">"Event Types"</label>
            <div class="checkbox-group">
                <For
                    each=move || available_types.clone()
                    key=|item| format!("{:?}", item.0)
                    children=move |(event_type, label)| {
                        // Clone event_type before closures to avoid move conflicts
                        let event_type_for_check = event_type.clone();
                        let event_type_for_toggle = event_type.clone();

                        let is_selected = Memo::new(move |_| {
                            selected.get().contains(&event_type_for_check)
                        });

                        let toggle_selection = move |_| {
                            on_change.update(|types| {
                                if let Some(pos) = types.iter().position(|t| *t == event_type_for_toggle) {
                                    types.remove(pos);
                                } else {
                                    types.push(event_type_for_toggle.clone());
                                }
                            });
                        };

                        view! {
                            <label class="checkbox-item">
                                <input
                                    type="checkbox"
                                    checked=is_selected
                                    on:change=toggle_selection
                                />
                                <span class="checkbox-label">{label}</span>
                            </label>
                        }
                    }
                />
            </div>
        </div>
    }
}

#[component]
pub fn SeverityFilter(
    selected: ReadSignal<Vec<ActivitySeverity>>,
    on_change: WriteSignal<Vec<ActivitySeverity>>,
) -> impl IntoView {
    let available_severities = vec![
        (ActivitySeverity::Info, "Info"),
        (ActivitySeverity::Low, "Low"),
        (ActivitySeverity::Medium, "Medium"),
        (ActivitySeverity::High, "High"),
        (ActivitySeverity::Critical, "Critical"),
    ];

    view! {
        <div class="filter-group">
            <label class="filter-label">"Severity"</label>
            <div class="checkbox-group">
                <For
                    each=move || available_severities.clone()
                    key=|item| format!("{:?}", item.0)
                    children=move |(severity, label)| {
                        // Clone severity before closures to avoid move conflicts
                        let severity_for_check = severity.clone();
                        let severity_for_toggle = severity.clone();
                        let severity_for_display = severity.clone();

                        let is_selected = Memo::new(move |_| {
                            selected.get().contains(&severity_for_check)
                        });

                        let toggle_selection = move |_| {
                            on_change.update(|severities| {
                                if let Some(pos) = severities.iter().position(|s| *s == severity_for_toggle) {
                                    severities.remove(pos);
                                } else {
                                    severities.push(severity_for_toggle.clone());
                                }
                            });
                        };

                        view! {
                            <label class="checkbox-item">
                                <input
                                    type="checkbox"
                                    checked=is_selected
                                    on:change=toggle_selection
                                />
                                <span class=format!("checkbox-label severity-{:?}", severity_for_display).to_lowercase()>
                                    {label}
                                </span>
                            </label>
                        }
                    }
                />
            </div>
        </div>
    }
}

// System Health Widget with Traffic Light Status

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemHealthConfig {
    pub title: String,
    pub show_details: bool,
    pub auto_refresh: bool,
    pub refresh_interval: u32,
    pub thresholds: HealthThresholds,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthThresholds {
    pub cpu_warning: f64,
    pub cpu_critical: f64,
    pub memory_warning: f64,
    pub memory_critical: f64,
    pub disk_warning: f64,
    pub disk_critical: f64,
}

impl Default for HealthThresholds {
    fn default() -> Self {
        Self {
            cpu_warning: 70.0,
            cpu_critical: 90.0,
            memory_warning: 80.0,
            memory_critical: 95.0,
            disk_warning: 85.0,
            disk_critical: 95.0,
        }
    }
}

impl Default for SystemHealthConfig {
    fn default() -> Self {
        Self {
            title: "System Health".to_string(),
            show_details: true,
            auto_refresh: true,
            refresh_interval: 15,
            thresholds: HealthThresholds::default(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemHealthData {
    pub overall_status: SystemStatus,
    pub cpu_usage: f64,
    pub memory_usage: f64,
    pub disk_usage: f64,
    pub network_status: SystemStatus,
    pub services: Vec<ServiceHealth>,
    pub uptime: String,
    pub last_updated: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceHealth {
    pub name: String,
    pub status: SystemStatus,
    pub response_time: Option<u32>, // milliseconds
    pub last_check: DateTime<Utc>,
    pub error_message: Option<String>,
}

#[component]
pub fn SystemHealthWidget(
    config: SystemHealthConfig,
    data: ReadSignal<SystemHealthData>,
) -> impl IntoView {
    let overall_status_class = Memo::new(move |_| match data.get().overall_status.level {
        crate::types::HealthStatus::Healthy => "status-healthy",
        crate::types::HealthStatus::Warning => "status-warning",
        crate::types::HealthStatus::Critical => "status-critical",
        crate::types::HealthStatus::Unknown => "status-unknown",
    });

    view! {
        <div class="system-health-widget">
            <div class="widget-header">
                <h3 class="widget-title">{config.title.clone()}</h3>
                <div class="overall-status">
                    <div class=format!("status-indicator {}", overall_status_class.get())>
                        <div class="status-light"></div>
                        <span class="status-text">
                            {move || format!("{:?}", data.get().overall_status)}
                        </span>
                    </div>
                </div>
            </div>

            <div class="health-overview">
                <div class="metric-grid">
                    <HealthMetric
                        label="CPU"
                        value=move || data.get().cpu_usage
                        unit="%"
                        thresholds=(config.thresholds.cpu_warning, config.thresholds.cpu_critical)
                        icon="bi-cpu"
                    />
                    <HealthMetric
                        label="Memory"
                        value=move || data.get().memory_usage
                        unit="%"
                        thresholds=(config.thresholds.memory_warning, config.thresholds.memory_critical)
                        icon="bi-memory"
                    />
                    <HealthMetric
                        label="Disk"
                        value=move || data.get().disk_usage
                        unit="%"
                        thresholds=(config.thresholds.disk_warning, config.thresholds.disk_critical)
                        icon="bi-hdd"
                    />
                    <HealthMetric
                        label="Network"
                        value=move || match data.get().network_status.level {
                            crate::types::HealthStatus::Healthy => 100.0,
                            crate::types::HealthStatus::Warning => 50.0,
                            crate::types::HealthStatus::Critical => 0.0,
                            crate::types::HealthStatus::Unknown => 0.0,
                        }
                        unit=""
                        thresholds=(50.0, 90.0)
                        icon="bi-wifi"
                        format_value=Box::new(|val: f64| {
                            match val as u8 {
                                100 => "Online".to_string(),
                                50 => "Degraded".to_string(),
                                0 => "Offline".to_string(),
                                _ => "Unknown".to_string(),
                            }
                        })
                    />
                </div>
            </div>

            <Show when=move || config.show_details>
                <div class="health-details">
                    <div class="uptime-info">
                        <i class="bi-clock"></i>
                        <span>"Uptime: " {move || data.get().uptime}</span>
                    </div>

                    <div class="services-health">
                        <h4>"Services"</h4>
                        <div class="services-list">
                            <For
                                each=move || data.get().services
                                key=|service| service.name.clone()
                                children=move |service| {
                                    view! {
                                        <ServiceHealthItem service=service />
                                    }
                                }
                            />
                        </div>
                    </div>
                </div>
            </Show>

            <div class="widget-footer">
                <small class="text-muted">
                    "Last updated: "
                    {move || data.get().last_updated.format("%H:%M:%S").to_string()}
                </small>
            </div>
        </div>
    }
}

#[component]
pub fn HealthMetric(
    label: &'static str,
    value: impl Fn() -> f64 + 'static + Send + Sync,
    unit: &'static str,
    thresholds: (f64, f64), // (warning, critical)
    icon: &'static str,
    #[prop(optional)] format_value: Option<Box<dyn Fn(f64) -> String + 'static + Send + Sync>>,
) -> impl IntoView {
    // Create a memo for the current value to avoid calling value() multiple times
    let current_value = Memo::new(move |_| value());

    let status_class = Memo::new(move |_| {
        let val = current_value.get();
        let (warning, critical) = thresholds;

        if val >= critical {
            "metric-critical"
        } else if val >= warning {
            "metric-warning"
        } else {
            "metric-healthy"
        }
    });

    let formatted_value = move || {
        let val = current_value.get();
        if let Some(formatter) = &format_value {
            formatter(val)
        } else {
            format!("{:.1}{}", val, unit)
        }
    };

    view! {
        <div class=format!("health-metric {}", status_class.get())>
            <div class="metric-icon">
                <i class=icon></i>
            </div>
            <div class="metric-content">
                <div class="metric-value">{formatted_value}</div>
                <div class="metric-label">{label}</div>
            </div>
            <div class="metric-status">
                <div class="status-dot"></div>
            </div>
        </div>
    }
}

#[component]
pub fn ServiceHealthItem(service: ServiceHealth) -> impl IntoView {
    // Clone fields before creating closures to avoid move conflicts
    let status_level = service.status.level;
    let status_level_for_icon = service.status.level;
    let name = service.name.clone();
    let response_time = service.response_time;

    // Create signal for error_message to avoid multiple capture conflicts
    let (error_message_opt, _) = signal(service.error_message.clone());

    let status_class = move || match status_level {
        crate::types::HealthStatus::Healthy => "service-healthy",
        crate::types::HealthStatus::Warning => "service-warning",
        crate::types::HealthStatus::Critical => "service-critical",
        crate::types::HealthStatus::Unknown => "service-unknown",
    };

    let status_icon = move || match status_level_for_icon {
        crate::types::HealthStatus::Healthy => "bi-check-circle-fill",
        crate::types::HealthStatus::Warning => "bi-exclamation-triangle-fill",
        crate::types::HealthStatus::Critical => "bi-x-circle-fill",
        crate::types::HealthStatus::Unknown => "bi-question-circle-fill",
    };

    view! {
        <div class=format!("service-item {}", status_class())>
            <div class="service-status">
                <i class=status_icon></i>
            </div>
            <div class="service-info">
                <span class="service-name">{name}</span>
                <Show when=move || response_time.is_some()>
                    <span class="service-response-time">
                        {response_time.map(|rt| format!("{}ms", rt)).unwrap_or_default()}
                    </span>
                </Show>
            </div>
            <Show when=move || error_message_opt.get().is_some()>
                <div class="service-error">
                    <i class="bi-exclamation-triangle"></i>
                    <span>{move || error_message_opt.get().unwrap_or_default()}</span>
                </div>
            </Show>
        </div>
    }
}

// Additional widget types

#[component]
pub fn MetricWidget(config: MetricConfig, data: ReadSignal<Option<MetricData>>) -> impl IntoView {
    view! {
        <div class="metric-widget">
            <div class="metric-header">
                <h3 class="metric-title">{config.title}</h3>
            </div>
            <div class="metric-body">
                // Implementation for metric display
                {move || {
                    if let Some(data) = data.get() {
                        format!("{:.2} {}", data.value, config.unit)
                    } else {
                        "Loading...".to_string()
                    }
                }}
            </div>
        </div>
    }
}

// Supporting types and configurations

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricConfig {
    pub title: String,
    pub unit: String,
    pub format: String,
    pub thresholds: Option<(f64, f64)>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricData {
    pub value: f64,
    pub timestamp: DateTime<Utc>,
    pub trend: Option<f64>, // percentage change
}

impl Default for MetricConfig {
    fn default() -> Self {
        Self {
            title: "Metric".to_string(),
            unit: "".to_string(),
            format: "{:.2}".to_string(),
            thresholds: None,
        }
    }
}
