Documentation
use markdownx::parser::Node;
use markdownx::{Component, Error};
use std::collections::HashMap;

/// RatingComponent for displaying star ratings
pub struct RatingComponent;

impl RatingComponent {
    pub fn new() -> Self {
        Self
    }
}

impl Component for RatingComponent {
    fn name(&self) -> &str {
        "rating"
    }

    fn render(
        &self,
        attributes: &HashMap<String, String>,
        _children: &[Node],
    ) -> Result<String, Error> {
        // Get rating attributes with defaults
        let value = attributes
            .get("value")
            .and_then(|v| v.parse::<f32>().ok())
            .unwrap_or(0.0);

        let max = attributes
            .get("max")
            .and_then(|v| v.parse::<u8>().ok())
            .unwrap_or(5);

        let size = attributes.get("size").unwrap_or(&"medium".to_string());

        // Clamp value to 0..max
        let value = value.max(0.0).min(max as f32);

        // Generate stars
        let mut stars_html = String::new();

        for i in 1..=max {
            let fill = if i as f32 <= value {
                "full"
            } else if (i as f32 - 0.5) <= value {
                "half"
            } else {
                "empty"
            };

            stars_html.push_str(&format!(
                r#"<span class="markrust-star markrust-star-{}">{}</span>"#,
                fill,
                get_star_svg(fill)
            ));
        }

        // Add numerical value if requested
        let value_html = if attributes.get("show_value").is_some() {
            format!(r#"<span class="markrust-rating-value">{}</span>"#, value)
        } else {
            String::new()
        };

        // Create the HTML for the rating
        Ok(format!(
            r#"<div class="markrust-rating markrust-rating-{size}">
                {stars_html}
                {value_html}
            </div>"#,
            size = size,
            stars_html = stars_html,
            value_html = value_html
        ))
    }

    fn css(&self) -> Option<String> {
        Some(
            r#"
/* Rating component styles */
.markrust-rating {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.markrust-rating-small {
  font-size: 1rem;
}

.markrust-rating-medium {
  font-size: 1.5rem;
}

.markrust-rating-large {
  font-size: 2rem;
}

.markrust-star {
  color: #d1d5db;
  line-height: 1;
}

.markrust-star-full {
  color: #f59e0b;
}

.markrust-star-half {
  color: #f59e0b;
}

.markrust-rating-value {
  margin-left: 0.5rem;
  font-weight: 600;
}
        "#
            .to_string(),
        )
    }
}

fn get_star_svg(fill: &str) -> &'static str {
    match fill {
        "full" => "",
        "half" => "",
        _ => "",
    }
}