//! Status bar widget for displaying application status
//!
//! Implements R-WIDGET-COMPOSITION:
//! - Simple, focused widget for status display
//! - Theme-aware styling
//! - Support for status indicators with colors

use crate::config::{Status, Theme};
use ratatui::prelude::*;
use ratatui::widgets::Paragraph;

/// Status bar item with label and status
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StatusItem {
    /// Item label
    label: String,
    /// Item status
    status: Status,
    /// Optional value to display
    value: Option<String>,
}

impl StatusItem {
    /// Create a new status item
    #[must_use]
    pub const fn new(label: String, status: Status) -> Self {
        Self {
            label,
            status,
            value: None,
        }
    }

    /// Set the value
    #[must_use]
    pub fn with_value(mut self, value: String) -> Self {
        self.value = Some(value);
        self
    }

    /// Get label
    #[must_use]
    pub fn label(&self) -> &str {
        &self.label
    }

    /// Get status
    #[must_use]
    pub const fn status(&self) -> Status {
        self.status
    }

    /// Get value if set
    #[must_use]
    pub fn value(&self) -> Option<&str> {
        self.value.as_deref()
    }
}

/// Status bar widget
///
/// Simple widget for displaying status information at the bottom of the screen.
///
/// # Example
///
/// ```ignore
/// let mut status_bar = StatusBar::new()
///     .add_item(StatusItem::new("Status".to_string(), Status::Normal)
///         .value("Ready".to_string()))
///     .add_item(StatusItem::new("Mode".to_string(), Status::Active)
///         .value("Insert".to_string()));
///
/// status_bar.render(&theme, frame, area);
/// ```
#[derive(Clone, Debug)]
pub struct StatusBar {
    /// Status items to display
    items: Vec<StatusItem>,
}

impl StatusBar {
    /// Create a new status bar
    #[must_use]
    pub const fn new() -> Self {
        Self { items: Vec::new() }
    }

    /// Add a status item
    #[must_use]
    pub fn add_item(mut self, item: StatusItem) -> Self {
        self.items.push(item);
        self
    }

    /// Get status items
    #[must_use]
    pub fn items(&self) -> &[StatusItem] {
        &self.items
    }

    /// Update item status by label
    pub fn set_status(&mut self, label: &str, status: Status) {
        if let Some(item) = self.items.iter_mut().find(|i| i.label == label) {
            item.status = status;
        }
    }

    /// Update item value by label
    pub fn set_value(&mut self, label: &str, value: String) {
        if let Some(item) = self.items.iter_mut().find(|i| i.label == label) {
            item.value = Some(value);
        }
    }

    /// Render the status bar
    pub fn render(&self, theme: &Theme, frame: &mut Frame, area: Rect) {
        if area.height < 1 {
            return;
        }

        let mut spans = Vec::new();

        for (idx, item) in self.items.iter().enumerate() {
            if idx > 0 {
                spans.push(Span::raw(" │ "));
            }

            let label_span = Span::styled(format!("{}: ", item.label()), theme.dimmed_style());
            spans.push(label_span);

            let value_text = item.value().unwrap_or("─").to_string();

            let value_span = Span::styled(value_text, item.status().style());
            spans.push(value_span);
        }

        let line = Line::from(spans);
        let paragraph = Paragraph::new(line)
            .style(theme.normal_style())
            .alignment(Alignment::Left);

        frame.render_widget(paragraph, area);
    }
}

impl Default for StatusBar {
    fn default() -> Self {
        Self::new()
            .add_item(StatusItem::new("Status".to_string(), Status::Normal))
            .add_item(StatusItem::new("Mode".to_string(), Status::Normal))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_status_item_new() {
        let item = StatusItem::new("Status".to_string(), Status::Normal);
        assert_eq!(item.label(), "Status");
        assert_eq!(item.status(), Status::Normal);
        assert_eq!(item.value(), None);
    }

    #[test]
    fn test_status_item_value() {
        let item =
            StatusItem::new("Status".to_string(), Status::Normal).with_value("Ready".to_string());
        assert_eq!(item.value(), Some("Ready"));
    }

    #[test]
    fn test_status_item_clone() {
        let item1 = StatusItem::new("Status".to_string(), Status::Success);
        let item2 = item1.clone();
        assert_eq!(item1, item2);
    }

    #[test]
    fn test_status_bar_new() {
        let bar = StatusBar::new();
        assert_eq!(bar.items().len(), 0);
    }

    #[test]
    fn test_status_bar_add_item() {
        let bar = StatusBar::new()
            .add_item(StatusItem::new("Status".to_string(), Status::Normal))
            .add_item(StatusItem::new("Mode".to_string(), Status::Active));

        assert_eq!(bar.items().len(), 2);
    }

    #[test]
    fn test_status_bar_set_status() {
        let mut bar =
            StatusBar::new().add_item(StatusItem::new("Status".to_string(), Status::Normal));

        bar.set_status("Status", Status::Success);
        assert_eq!(bar.items()[0].status(), Status::Success);
    }

    #[test]
    fn test_status_bar_set_value() {
        let mut bar =
            StatusBar::new().add_item(StatusItem::new("Status".to_string(), Status::Normal));

        bar.set_value("Status", "Ready".to_string());
        assert_eq!(bar.items()[0].value(), Some("Ready"));
    }

    #[test]
    fn test_status_bar_default() {
        let bar = StatusBar::default();
        assert_eq!(bar.items().len(), 2);
        assert_eq!(bar.items()[0].label(), "Status");
    }

    #[test]
    fn test_status_bar_clone() {
        let bar1 = StatusBar::new().add_item(StatusItem::new("Status".to_string(), Status::Normal));
        let bar2 = bar1.clone();
        assert_eq!(bar1.items().len(), bar2.items().len());
    }

    #[test]
    fn test_status_item_status_normal() {
        let item = StatusItem::new("Test".to_string(), Status::Normal);
        assert_eq!(item.status(), Status::Normal);
    }

    #[test]
    fn test_status_item_status_error() {
        let item = StatusItem::new("Test".to_string(), Status::Error);
        assert_eq!(item.status(), Status::Error);
    }

    #[test]
    fn test_status_item_status_success() {
        let item = StatusItem::new("Test".to_string(), Status::Success);
        assert_eq!(item.status(), Status::Success);
    }

    #[test]
    fn test_status_item_status_warning() {
        let item = StatusItem::new("Test".to_string(), Status::Warning);
        assert_eq!(item.status(), Status::Warning);
    }

    #[test]
    fn test_status_bar_multiple_updates() {
        let mut bar = StatusBar::new()
            .add_item(StatusItem::new("Status".to_string(), Status::Normal))
            .add_item(StatusItem::new("Mode".to_string(), Status::Normal));

        bar.set_status("Status", Status::Success);
        bar.set_status("Mode", Status::Active);
        bar.set_value("Status", "Ready".to_string());

        assert_eq!(bar.items()[0].status(), Status::Success);
        assert_eq!(bar.items()[1].status(), Status::Active);
        assert_eq!(bar.items()[0].value(), Some("Ready"));
    }
}
