use leptos::either::EitherOf7;
use leptos::prelude::*;

// * 🧪 cargo test --package icons --lib --features leptos

#[derive(Debug, Clone)]
pub enum SvgElement {
    Path { d: String },
    Circle { cx: String, cy: String, r: String },
    Rect { x: String, y: String, width: String, height: String, rx: Option<String>, ry: Option<String> },
    Ellipse { cx: String, cy: String, rx: String, ry: String },
    Line { x1: String, y1: String, x2: String, y2: String },
    Polyline { points: String },
    Polygon { points: String },
    // Add more SVG elements as needed (g, defs, etc.)
}

impl SvgElement {
    pub fn to_leptos_view(&self) -> impl IntoView + use<> {
        match self {
            SvgElement::Path { d } => EitherOf7::A(view! { <path d=d /> }),
            SvgElement::Circle { cx, cy, r } => EitherOf7::B(view! { <circle cx=cx cy=cy r=r /> }),
            SvgElement::Rect { x, y, width, height, rx, ry } => EitherOf7::C(match (rx, ry) {
                (Some(rx), Some(ry)) => view! { <rect x=x y=y width=width height=height rx=rx ry=ry /> },
                (Some(rx), None) => view! { <rect x=x y=y width=width height=height rx=rx /> },
                (None, Some(ry)) => view! { <rect x=x y=y width=width height=height ry=ry /> },
                (None, None) => view! { <rect x=x y=y width=width height=height /> },
            }),
            SvgElement::Ellipse { cx, cy, rx, ry } => EitherOf7::D(view! { <ellipse cx=cx cy=cy rx=rx ry=ry /> }),
            SvgElement::Line { x1, y1, x2, y2 } => EitherOf7::E(view! { <line x1=x1 y1=y1 x2=x2 y2=y2 /> }),
            SvgElement::Polyline { points } => EitherOf7::F(view! { <polyline points=points /> }),
            SvgElement::Polygon { points } => EitherOf7::G(view! { <polygon points=points /> }),
        }
    }
}

// Helper function to parse SVG content and return structured elements
pub fn parse_svg_elements(svg_content: &str) -> Vec<SvgElement> {
    svg_content
        .lines()
        .filter_map(|line| {
            let line = line.trim();
            if line.is_empty() {
                return None;
            }

            // Parse path, circle, rect, ellipse, line, polyline, and polygon elements
            if line.starts_with("<path ") {
                parse_path_element(line)
            } else if line.starts_with("<circle ") {
                parse_circle_element(line)
            } else if line.starts_with("<rect ") {
                parse_rect_element(line)
            } else if line.starts_with("<ellipse ") {
                parse_ellipse_element(line)
            } else if line.starts_with("<line ") {
                parse_line_element(line)
            } else if line.starts_with("<polyline ") {
                parse_polyline_element(line)
            } else if line.starts_with("<polygon ") {
                parse_polygon_element(line)
            } else {
                None
            }
        })
        .collect()
}

// Helper function to extract attributes from SVG element strings
fn extract_attribute(line: &str, attr: &str) -> Option<String> {
    if let Some(start) = line.find(&format!("{}=\"", attr)) {
        let start = start + attr.len() + 2; // Skip 'attr="'
        if let Some(end) = line[start..].find('"') {
            return Some(line[start..start + end].to_string());
        }
    }
    None
}

// Specific parsers for path, circle, rect, ellipse, line, polyline, and polygon elements
fn parse_path_element(line: &str) -> Option<SvgElement> {
    extract_attribute(line, "d").map(|d| SvgElement::Path { d })
}

fn parse_circle_element(line: &str) -> Option<SvgElement> {
    let cx = extract_attribute(line, "cx")?;
    let cy = extract_attribute(line, "cy")?;
    let r = extract_attribute(line, "r")?;
    Some(SvgElement::Circle { cx, cy, r })
}

fn parse_rect_element(line: &str) -> Option<SvgElement> {
    let x = extract_attribute(line, "x")?;
    let y = extract_attribute(line, "y")?;
    let width = extract_attribute(line, "width")?;
    let height = extract_attribute(line, "height")?;
    let rx = extract_attribute(line, "rx");
    let ry = extract_attribute(line, "ry");
    Some(SvgElement::Rect { x, y, width, height, rx, ry })
}

fn parse_ellipse_element(line: &str) -> Option<SvgElement> {
    let cx = extract_attribute(line, "cx")?;
    let cy = extract_attribute(line, "cy")?;
    let rx = extract_attribute(line, "rx")?;
    let ry = extract_attribute(line, "ry")?;
    Some(SvgElement::Ellipse { cx, cy, rx, ry })
}

fn parse_line_element(line: &str) -> Option<SvgElement> {
    let x1 = extract_attribute(line, "x1")?;
    let y1 = extract_attribute(line, "y1")?;
    let x2 = extract_attribute(line, "x2")?;
    let y2 = extract_attribute(line, "y2")?;
    Some(SvgElement::Line { x1, y1, x2, y2 })
}

fn parse_polyline_element(line: &str) -> Option<SvgElement> {
    let points = extract_attribute(line, "points")?;
    Some(SvgElement::Polyline { points })
}

fn parse_polygon_element(line: &str) -> Option<SvgElement> {
    let points = extract_attribute(line, "points")?;
    Some(SvgElement::Polygon { points })
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/*                        🧪 TESTS 🧪                         */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

    #[test]
    fn test_svg_element_path_creation() {
        let path = SvgElement::Path { d: "M10 10 L20 20".to_string() };

        match path {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected Path variant"),
        }
    }

    #[test]
    fn test_svg_element_circle_creation() {
        let circle = SvgElement::Circle { cx: "10".to_string(), cy: "20".to_string(), r: "5".to_string() };

        match circle {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "10");
                assert_eq!(cy, "20");
                assert_eq!(r, "5");
            }
            _ => panic!("Expected Circle variant"),
        }
    }

    #[test]
    fn test_extract_attribute_success() {
        let line = r#"<path d="M10 10 L20 20" fill="red" />"#;

        assert_eq!(extract_attribute(line, "d"), Some("M10 10 L20 20".to_string()));
        assert_eq!(extract_attribute(line, "fill"), Some("red".to_string()));
    }

    #[test]
    fn test_extract_attribute_not_found() {
        let line = r#"<path d="M10 10 L20 20" />"#;

        assert_eq!(extract_attribute(line, "fill"), None);
        assert_eq!(extract_attribute(line, "stroke"), None);
    }

    #[test]
    fn test_extract_attribute_empty_value() {
        let line = r#"<path d="" />"#;

        assert_eq!(extract_attribute(line, "d"), Some("".to_string()));
    }

    #[test]
    fn test_parse_path_element_success() {
        let line = r#"<path d="M10 10 L20 20" />"#;
        let result = parse_path_element(line);

        match result {
            Some(SvgElement::Path { d }) => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected Some(Path)"),
        }
    }

    #[test]
    fn test_parse_path_element_missing_d() {
        let line = r#"<path fill="red" />"#;
        let result = parse_path_element(line);

        assert!(result.is_none());
    }

    #[test]
    fn test_parse_circle_element_success() {
        let line = r#"<circle cx="10" cy="20" r="5" />"#;
        let result = parse_circle_element(line);

        match result {
            Some(SvgElement::Circle { cx, cy, r }) => {
                assert_eq!(cx, "10");
                assert_eq!(cy, "20");
                assert_eq!(r, "5");
            }
            _ => panic!("Expected Some(Circle)"),
        }
    }

    #[test]
    fn test_parse_circle_element_missing_attributes() {
        let line = r#"<circle cx="10" />"#;
        let result = parse_circle_element(line);

        assert!(result.is_none());
    }

    #[test]
    fn test_parse_svg_elements_mixed_content() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <circle cx="15" cy="25" r="3" />
    <rect x="0" y="0" width="10" height="10" />
    <path d="M0 0 L10 10" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        // Should find 2 path elements, 1 circle element, and 1 rect element = 4 total
        assert_eq!(elements.len(), 4);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected second element to be Circle"),
        }

        match &elements[2] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "10");
                assert_eq!(height, "10");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected third element to be Rect"),
        }

        match &elements[3] {
            SvgElement::Path { d } => assert_eq!(d, "M0 0 L10 10"),
            _ => panic!("Expected fourth element to be Path"),
        }
    }

    #[test]
    fn test_parse_svg_elements_empty_content() {
        let svg_content = "";
        let elements = parse_svg_elements(svg_content);
        assert!(elements.is_empty());
    }

    #[test]
    fn test_parse_svg_elements_whitespace_only() {
        let svg_content = "   \n   \t   \n   ";
        let elements = parse_svg_elements(svg_content);
        assert!(elements.is_empty());
    }

    #[test]
    fn test_parse_svg_elements_no_matching_elements() {
        let svg_content = r#"
<svg>
    <g fill="red">
        <text x="10" y="20">Hello</text>
        <image href="image.png" />
    </g>
    <defs>
        <pattern id="pattern1" />
    </defs>
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);
        assert!(elements.is_empty());
    }

    #[test]
    fn test_parse_svg_elements_complex_path() {
        let svg_content = r#"<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />"#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 1);
        match &elements[0] {
            SvgElement::Path { d } => {
                assert_eq!(
                    d,
                    "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
                );
            }
            _ => panic!("Expected Path element"),
        }
    }

    #[test]
    fn test_parse_svg_elements_multiple_paths_and_circles() {
        let svg_content = r#"
    <path d="M1 1 L2 2" />
    <circle cx="1" cy="1" r="1" />
    <path d="M3 3 L4 4" />
    <circle cx="2" cy="2" r="2" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 4);

        // Verify the sequence is preserved
        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "1");
                assert_eq!(cy, "1");
                assert_eq!(r, "1");
            }
            _ => panic!("Expected second element to be Circle"),
        }

        match &elements[2] {
            SvgElement::Path { d } => assert_eq!(d, "M3 3 L4 4"),
            _ => panic!("Expected third element to be Path"),
        }

        match &elements[3] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "2");
                assert_eq!(cy, "2");
                assert_eq!(r, "2");
            }
            _ => panic!("Expected fourth element to be Circle"),
        }
    }

    // ---- RECT TESTS ----

    #[test]
    fn test_svg_element_rect_creation() {
        let rect = SvgElement::Rect {
            x: "10".to_string(),
            y: "20".to_string(),
            width: "100".to_string(),
            height: "50".to_string(),
            rx: None,
            ry: None,
        };

        match rect {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "10");
                assert_eq!(y, "20");
                assert_eq!(width, "100");
                assert_eq!(height, "50");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected Rect variant"),
        }
    }

    #[test]
    fn test_svg_element_rect_with_rounded_corners() {
        let rect = SvgElement::Rect {
            x: "0".to_string(),
            y: "0".to_string(),
            width: "50".to_string(),
            height: "50".to_string(),
            rx: Some("5".to_string()),
            ry: Some("10".to_string()),
        };

        match rect {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "50");
                assert_eq!(rx.as_ref(), Some(&"5".to_string()));
                assert_eq!(ry.as_ref(), Some(&"10".to_string()));
            }
            _ => panic!("Expected Rect variant"),
        }
    }

    #[test]
    fn test_parse_rect_element_basic() {
        let line = r#"<rect x="10" y="20" width="100" height="50" />"#;
        let result = parse_rect_element(line);

        match result {
            Some(SvgElement::Rect { x, y, width, height, rx, ry }) => {
                assert_eq!(x, "10");
                assert_eq!(y, "20");
                assert_eq!(width, "100");
                assert_eq!(height, "50");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected Some(Rect)"),
        }
    }

    #[test]
    fn test_parse_rect_element_with_rx_ry() {
        let line = r#"<rect x="0" y="0" width="50" height="30" rx="5" ry="10" />"#;
        let result = parse_rect_element(line);

        match result {
            Some(SvgElement::Rect { x, y, width, height, rx, ry }) => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert_eq!(rx.as_ref(), Some(&"5".to_string()));
                assert_eq!(ry.as_ref(), Some(&"10".to_string()));
            }
            _ => panic!("Expected Some(Rect)"),
        }
    }

    #[test]
    fn test_parse_rect_element_with_only_rx() {
        let line = r#"<rect x="0" y="0" width="50" height="30" rx="5" />"#;
        let result = parse_rect_element(line);

        match result {
            Some(SvgElement::Rect { x, y, width, height, rx, ry }) => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert_eq!(rx.as_ref(), Some(&"5".to_string()));
                assert!(ry.is_none());
            }
            _ => panic!("Expected Some(Rect)"),
        }
    }

    #[test]
    fn test_parse_rect_element_missing_required_attributes() {
        let line = r#"<rect x="10" y="20" />"#;
        let result = parse_rect_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_rect_element_missing_width() {
        let line = r#"<rect x="10" y="20" height="50" />"#;
        let result = parse_rect_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_svg_elements_with_rect() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <rect x="0" y="0" width="50" height="30" />
    <circle cx="15" cy="25" r="3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected second element to be Rect"),
        }

        match &elements[2] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected third element to be Circle"),
        }
    }

    #[test]
    fn test_parse_svg_elements_mixed_with_rounded_rect() {
        let svg_content = r#"
    <rect x="10" y="10" width="80" height="60" rx="15" ry="20" />
    <path d="M1 1 L2 2" />
    <rect x="0" y="0" width="10" height="10" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "10");
                assert_eq!(y, "10");
                assert_eq!(width, "80");
                assert_eq!(height, "60");
                assert_eq!(rx.as_ref(), Some(&"15".to_string()));
                assert_eq!(ry.as_ref(), Some(&"20".to_string()));
            }
            _ => panic!("Expected first element to be Rect"),
        }

        match &elements[1] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected second element to be Path"),
        }

        match &elements[2] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "10");
                assert_eq!(height, "10");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected third element to be Rect"),
        }
    }

    // ---- ELLIPSE TESTS ----

    #[test]
    fn test_svg_element_ellipse_creation() {
        let ellipse = SvgElement::Ellipse {
            cx: "50".to_string(),
            cy: "100".to_string(),
            rx: "20".to_string(),
            ry: "30".to_string(),
        };

        match ellipse {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "50");
                assert_eq!(cy, "100");
                assert_eq!(rx, "20");
                assert_eq!(ry, "30");
            }
            _ => panic!("Expected Ellipse variant"),
        }
    }

    #[test]
    fn test_parse_ellipse_element_success() {
        let line = r#"<ellipse cx="50" cy="100" rx="20" ry="30" />"#;
        let result = parse_ellipse_element(line);

        match result {
            Some(SvgElement::Ellipse { cx, cy, rx, ry }) => {
                assert_eq!(cx, "50");
                assert_eq!(cy, "100");
                assert_eq!(rx, "20");
                assert_eq!(ry, "30");
            }
            _ => panic!("Expected Some(Ellipse)"),
        }
    }

    #[test]
    fn test_parse_ellipse_element_missing_cx() {
        let line = r#"<ellipse cy="100" rx="20" ry="30" />"#;
        let result = parse_ellipse_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_ellipse_element_missing_cy() {
        let line = r#"<ellipse cx="50" rx="20" ry="30" />"#;
        let result = parse_ellipse_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_ellipse_element_missing_rx() {
        let line = r#"<ellipse cx="50" cy="100" ry="30" />"#;
        let result = parse_ellipse_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_ellipse_element_missing_ry() {
        let line = r#"<ellipse cx="50" cy="100" rx="20" />"#;
        let result = parse_ellipse_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_svg_elements_with_ellipse() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <ellipse cx="50" cy="100" rx="20" ry="30" />
    <circle cx="15" cy="25" r="3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "50");
                assert_eq!(cy, "100");
                assert_eq!(rx, "20");
                assert_eq!(ry, "30");
            }
            _ => panic!("Expected second element to be Ellipse"),
        }

        match &elements[2] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected third element to be Circle"),
        }
    }

    #[test]
    fn test_parse_svg_elements_mixed_with_ellipse_and_rect() {
        let svg_content = r#"
    <ellipse cx="10" cy="20" rx="15" ry="25" />
    <rect x="0" y="0" width="50" height="30" />
    <path d="M1 1 L2 2" />
    <ellipse cx="100" cy="200" rx="5" ry="10" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 4);

        match &elements[0] {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "10");
                assert_eq!(cy, "20");
                assert_eq!(rx, "15");
                assert_eq!(ry, "25");
            }
            _ => panic!("Expected first element to be Ellipse"),
        }

        match &elements[1] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected second element to be Rect"),
        }

        match &elements[2] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected third element to be Path"),
        }

        match &elements[3] {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "100");
                assert_eq!(cy, "200");
                assert_eq!(rx, "5");
                assert_eq!(ry, "10");
            }
            _ => panic!("Expected fourth element to be Ellipse"),
        }
    }

    #[test]
    fn test_parse_svg_elements_ellipse_only() {
        let svg_content = r#"
    <ellipse cx="25" cy="75" rx="10" ry="20" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 1);

        match &elements[0] {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "25");
                assert_eq!(cy, "75");
                assert_eq!(rx, "10");
                assert_eq!(ry, "20");
            }
            _ => panic!("Expected element to be Ellipse"),
        }
    }

    // ---- LINE TESTS ----

    #[test]
    fn test_svg_element_line_creation() {
        let line = SvgElement::Line {
            x1: "10".to_string(),
            y1: "20".to_string(),
            x2: "100".to_string(),
            y2: "200".to_string(),
        };

        match line {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "10");
                assert_eq!(y1, "20");
                assert_eq!(x2, "100");
                assert_eq!(y2, "200");
            }
            _ => panic!("Expected Line variant"),
        }
    }

    #[test]
    fn test_parse_line_element_success() {
        let line = r#"<line x1="10" y1="20" x2="100" y2="200" />"#;
        let result = parse_line_element(line);

        match result {
            Some(SvgElement::Line { x1, y1, x2, y2 }) => {
                assert_eq!(x1, "10");
                assert_eq!(y1, "20");
                assert_eq!(x2, "100");
                assert_eq!(y2, "200");
            }
            _ => panic!("Expected Some(Line)"),
        }
    }

    #[test]
    fn test_parse_line_element_missing_x1() {
        let line = r#"<line y1="20" x2="100" y2="200" />"#;
        let result = parse_line_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_line_element_missing_y1() {
        let line = r#"<line x1="10" x2="100" y2="200" />"#;
        let result = parse_line_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_line_element_missing_x2() {
        let line = r#"<line x1="10" y1="20" y2="200" />"#;
        let result = parse_line_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_line_element_missing_y2() {
        let line = r#"<line x1="10" y1="20" x2="100" />"#;
        let result = parse_line_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_svg_elements_with_line() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <line x1="0" y1="0" x2="50" y2="50" />
    <circle cx="15" cy="25" r="3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "0");
                assert_eq!(y1, "0");
                assert_eq!(x2, "50");
                assert_eq!(y2, "50");
            }
            _ => panic!("Expected second element to be Line"),
        }

        match &elements[2] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected third element to be Circle"),
        }
    }

    #[test]
    fn test_parse_svg_elements_mixed_with_line() {
        let svg_content = r#"
    <line x1="5" y1="5" x2="15" y2="15" />
    <rect x="0" y="0" width="50" height="30" />
    <path d="M1 1 L2 2" />
    <line x1="100" y1="200" x2="300" y2="400" />
    <ellipse cx="25" cy="50" rx="10" ry="20" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 5);

        match &elements[0] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "5");
                assert_eq!(y1, "5");
                assert_eq!(x2, "15");
                assert_eq!(y2, "15");
            }
            _ => panic!("Expected first element to be Line"),
        }

        match &elements[1] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected second element to be Rect"),
        }

        match &elements[2] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected third element to be Path"),
        }

        match &elements[3] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "100");
                assert_eq!(y1, "200");
                assert_eq!(x2, "300");
                assert_eq!(y2, "400");
            }
            _ => panic!("Expected fourth element to be Line"),
        }

        match &elements[4] {
            SvgElement::Ellipse { cx, cy, rx, ry } => {
                assert_eq!(cx, "25");
                assert_eq!(cy, "50");
                assert_eq!(rx, "10");
                assert_eq!(ry, "20");
            }
            _ => panic!("Expected fifth element to be Ellipse"),
        }
    }

    #[test]
    fn test_parse_svg_elements_line_only() {
        let svg_content = r#"
    <line x1="0" y1="0" x2="100" y2="100" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 1);

        match &elements[0] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "0");
                assert_eq!(y1, "0");
                assert_eq!(x2, "100");
                assert_eq!(y2, "100");
            }
            _ => panic!("Expected element to be Line"),
        }
    }

    #[test]
    fn test_parse_svg_elements_multiple_lines() {
        let svg_content = r#"
    <line x1="0" y1="0" x2="10" y2="10" />
    <line x1="20" y1="20" x2="30" y2="30" />
    <line x1="40" y1="40" x2="50" y2="50" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        // Verify the sequence is preserved
        match &elements[0] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "0");
                assert_eq!(y1, "0");
                assert_eq!(x2, "10");
                assert_eq!(y2, "10");
            }
            _ => panic!("Expected first element to be Line"),
        }

        match &elements[1] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "20");
                assert_eq!(y1, "20");
                assert_eq!(x2, "30");
                assert_eq!(y2, "30");
            }
            _ => panic!("Expected second element to be Line"),
        }

        match &elements[2] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "40");
                assert_eq!(y1, "40");
                assert_eq!(x2, "50");
                assert_eq!(y2, "50");
            }
            _ => panic!("Expected third element to be Line"),
        }
    }

    #[test]
    fn test_parse_line_element_with_decimal_coordinates() {
        let line = r#"<line x1="10.5" y1="20.25" x2="100.75" y2="200.125" />"#;
        let result = parse_line_element(line);

        match result {
            Some(SvgElement::Line { x1, y1, x2, y2 }) => {
                assert_eq!(x1, "10.5");
                assert_eq!(y1, "20.25");
                assert_eq!(x2, "100.75");
                assert_eq!(y2, "200.125");
            }
            _ => panic!("Expected Some(Line)"),
        }
    }

    // ---- POLYLINE TESTS ----

    #[test]
    fn test_svg_element_polyline_creation() {
        let polyline = SvgElement::Polyline { points: "10,20 30,40 50,60".to_string() };

        match polyline {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "10,20 30,40 50,60");
            }
            _ => panic!("Expected Polyline variant"),
        }
    }

    #[test]
    fn test_parse_polyline_element_success() {
        let line = r#"<polyline points="10,20 30,40 50,60" />"#;
        let result = parse_polyline_element(line);

        match result {
            Some(SvgElement::Polyline { points }) => {
                assert_eq!(points, "10,20 30,40 50,60");
            }
            _ => panic!("Expected Some(Polyline)"),
        }
    }

    #[test]
    fn test_parse_polyline_element_missing_points() {
        let line = r#"<polyline stroke="red" />"#;
        let result = parse_polyline_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_polyline_element_empty_points() {
        let line = r#"<polyline points="" />"#;
        let result = parse_polyline_element(line);

        match result {
            Some(SvgElement::Polyline { points }) => {
                assert_eq!(points, "");
            }
            _ => panic!("Expected Some(Polyline) with empty points"),
        }
    }

    #[test]
    fn test_parse_svg_elements_with_polyline() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <polyline points="0,0 10,10 20,0" />
    <circle cx="15" cy="25" r="3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "0,0 10,10 20,0");
            }
            _ => panic!("Expected second element to be Polyline"),
        }

        match &elements[2] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected third element to be Circle"),
        }
    }

    #[test]
    fn test_parse_svg_elements_mixed_with_polyline() {
        let svg_content = r#"
    <polyline points="0,0 5,5 10,0 15,5" />
    <rect x="0" y="0" width="50" height="30" />
    <path d="M1 1 L2 2" />
    <line x1="100" y1="200" x2="300" y2="400" />
    <polyline points="20,20 25,25 30,20" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 5);

        match &elements[0] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "0,0 5,5 10,0 15,5");
            }
            _ => panic!("Expected first element to be Polyline"),
        }

        match &elements[1] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected second element to be Rect"),
        }

        match &elements[2] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected third element to be Path"),
        }

        match &elements[3] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "100");
                assert_eq!(y1, "200");
                assert_eq!(x2, "300");
                assert_eq!(y2, "400");
            }
            _ => panic!("Expected fourth element to be Line"),
        }

        match &elements[4] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "20,20 25,25 30,20");
            }
            _ => panic!("Expected fifth element to be Polyline"),
        }
    }

    #[test]
    fn test_parse_svg_elements_polyline_only() {
        let svg_content = r#"
    <polyline points="10,15 20,25 30,35 40,45" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 1);

        match &elements[0] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "10,15 20,25 30,35 40,45");
            }
            _ => panic!("Expected element to be Polyline"),
        }
    }

    #[test]
    fn test_parse_svg_elements_multiple_polylines() {
        let svg_content = r#"
    <polyline points="0,0 10,10" />
    <polyline points="20,20 30,30 40,40" />
    <polyline points="50,50 60,60 70,70 80,80" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        // Verify the sequence is preserved
        match &elements[0] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "0,0 10,10");
            }
            _ => panic!("Expected first element to be Polyline"),
        }

        match &elements[1] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "20,20 30,30 40,40");
            }
            _ => panic!("Expected second element to be Polyline"),
        }

        match &elements[2] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "50,50 60,60 70,70 80,80");
            }
            _ => panic!("Expected third element to be Polyline"),
        }
    }

    #[test]
    fn test_parse_polyline_element_with_decimal_coordinates() {
        let line = r#"<polyline points="10.5,20.25 30.75,40.125 50.5,60.25" />"#;
        let result = parse_polyline_element(line);

        match result {
            Some(SvgElement::Polyline { points }) => {
                assert_eq!(points, "10.5,20.25 30.75,40.125 50.5,60.25");
            }
            _ => panic!("Expected Some(Polyline)"),
        }
    }

    #[test]
    fn test_parse_polyline_element_complex_points() {
        let line = r#"<polyline points="11 3 11 11 14 8 17 11 17 3" />"#;
        let result = parse_polyline_element(line);

        match result {
            Some(SvgElement::Polyline { points }) => {
                assert_eq!(points, "11 3 11 11 14 8 17 11 17 3");
            }
            _ => panic!("Expected Some(Polyline)"),
        }
    }

    #[test]
    fn test_parse_svg_elements_with_album_structure() {
        // Test the actual structure from album.txt
        let svg_content = r#"
<svg>
    <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
    <polyline points="11 3 11 11 14 8 17 11 17 3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 2);

        match &elements[0] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "3");
                assert_eq!(y, "3");
                assert_eq!(width, "18");
                assert_eq!(height, "18");
                assert_eq!(rx.as_ref(), Some(&"2".to_string()));
                assert_eq!(ry.as_ref(), Some(&"2".to_string()));
            }
            _ => panic!("Expected first element to be Rect"),
        }

        match &elements[1] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "11 3 11 11 14 8 17 11 17 3");
            }
            _ => panic!("Expected second element to be Polyline"),
        }
    }

    // ---- POLYGON TESTS ----

    #[test]
    fn test_svg_element_polygon_creation() {
        let polygon = SvgElement::Polygon { points: "10,20 30,40 50,60".to_string() };

        match polygon {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "10,20 30,40 50,60");
            }
            _ => panic!("Expected Polygon variant"),
        }
    }

    #[test]
    fn test_parse_polygon_element_success() {
        let line = r#"<polygon points="10,20 30,40 50,60" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "10,20 30,40 50,60");
            }
            _ => panic!("Expected Some(Polygon)"),
        }
    }

    #[test]
    fn test_parse_polygon_element_missing_points() {
        let line = r#"<polygon fill="blue" />"#;
        let result = parse_polygon_element(line);
        assert!(result.is_none());
    }

    #[test]
    fn test_parse_polygon_element_empty_points() {
        let line = r#"<polygon points="" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "");
            }
            _ => panic!("Expected Some(Polygon) with empty points"),
        }
    }

    #[test]
    fn test_parse_svg_elements_with_polygon() {
        let svg_content = r#"
<svg>
    <path d="M10 10 L20 20" />
    <polygon points="0,0 10,10 20,0" />
    <circle cx="15" cy="25" r="3" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        match &elements[0] {
            SvgElement::Path { d } => assert_eq!(d, "M10 10 L20 20"),
            _ => panic!("Expected first element to be Path"),
        }

        match &elements[1] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "0,0 10,10 20,0");
            }
            _ => panic!("Expected second element to be Polygon"),
        }

        match &elements[2] {
            SvgElement::Circle { cx, cy, r } => {
                assert_eq!(cx, "15");
                assert_eq!(cy, "25");
                assert_eq!(r, "3");
            }
            _ => panic!("Expected third element to be Circle"),
        }
    }

    #[test]
    fn test_parse_svg_elements_mixed_with_polygon() {
        let svg_content = r#"
    <polygon points="0,0 5,5 10,0" />
    <rect x="0" y="0" width="50" height="30" />
    <path d="M1 1 L2 2" />
    <line x1="100" y1="200" x2="300" y2="400" />
    <polyline points="20,20 25,25 30,20" />
    <polygon points="40,40 45,45 50,40 45,35" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 6);

        match &elements[0] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "0,0 5,5 10,0");
            }
            _ => panic!("Expected first element to be Polygon"),
        }

        match &elements[1] {
            SvgElement::Rect { x, y, width, height, rx, ry } => {
                assert_eq!(x, "0");
                assert_eq!(y, "0");
                assert_eq!(width, "50");
                assert_eq!(height, "30");
                assert!(rx.is_none());
                assert!(ry.is_none());
            }
            _ => panic!("Expected second element to be Rect"),
        }

        match &elements[2] {
            SvgElement::Path { d } => assert_eq!(d, "M1 1 L2 2"),
            _ => panic!("Expected third element to be Path"),
        }

        match &elements[3] {
            SvgElement::Line { x1, y1, x2, y2 } => {
                assert_eq!(x1, "100");
                assert_eq!(y1, "200");
                assert_eq!(x2, "300");
                assert_eq!(y2, "400");
            }
            _ => panic!("Expected fourth element to be Line"),
        }

        match &elements[4] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "20,20 25,25 30,20");
            }
            _ => panic!("Expected fifth element to be Polyline"),
        }

        match &elements[5] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "40,40 45,45 50,40 45,35");
            }
            _ => panic!("Expected sixth element to be Polygon"),
        }
    }

    #[test]
    fn test_parse_svg_elements_polygon_only() {
        let svg_content = r#"
    <polygon points="10,15 20,25 30,35 25,45 15,45 5,35" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 1);

        match &elements[0] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "10,15 20,25 30,35 25,45 15,45 5,35");
            }
            _ => panic!("Expected element to be Polygon"),
        }
    }

    #[test]
    fn test_parse_svg_elements_multiple_polygons() {
        let svg_content = r#"
    <polygon points="0,0 10,10 0,20" />
    <polygon points="20,20 30,30 40,40 30,50" />
    <polygon points="50,50 60,60 70,70 80,80 70,90 60,80" />
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 3);

        // Verify the sequence is preserved
        match &elements[0] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "0,0 10,10 0,20");
            }
            _ => panic!("Expected first element to be Polygon"),
        }

        match &elements[1] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "20,20 30,30 40,40 30,50");
            }
            _ => panic!("Expected second element to be Polygon"),
        }

        match &elements[2] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "50,50 60,60 70,70 80,80 70,90 60,80");
            }
            _ => panic!("Expected third element to be Polygon"),
        }
    }

    #[test]
    fn test_parse_polygon_element_with_decimal_coordinates() {
        let line = r#"<polygon points="10.5,20.25 30.75,40.125 50.5,60.25" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "10.5,20.25 30.75,40.125 50.5,60.25");
            }
            _ => panic!("Expected Some(Polygon)"),
        }
    }

    #[test]
    fn test_parse_polygon_element_triangle() {
        let line = r#"<polygon points="100,50 150,100 50,100" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "100,50 150,100 50,100");
            }
            _ => panic!("Expected Some(Polygon)"),
        }
    }

    #[test]
    fn test_parse_polygon_element_star() {
        let line = r#"<polygon points="50,0 61,35 98,35 68,57 79,91 50,70 21,91 32,57 2,35 39,35" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "50,0 61,35 98,35 68,57 79,91 50,70 21,91 32,57 2,35 39,35");
            }
            _ => panic!("Expected Some(Polygon)"),
        }
    }

    #[test]
    fn test_parse_svg_elements_polygon_vs_polyline() {
        // Test that polygon and polyline are correctly differentiated
        let svg_content = r#"
<svg>
    <polyline points="0,0 10,10 20,0" />
    <polygon points="30,30 40,40 50,30" />
</svg>
        "#;

        let elements = parse_svg_elements(svg_content);

        assert_eq!(elements.len(), 2);

        match &elements[0] {
            SvgElement::Polyline { points } => {
                assert_eq!(points, "0,0 10,10 20,0");
            }
            _ => panic!("Expected first element to be Polyline"),
        }

        match &elements[1] {
            SvgElement::Polygon { points } => {
                assert_eq!(points, "30,30 40,40 50,30");
            }
            _ => panic!("Expected second element to be Polygon"),
        }
    }

    #[test]
    fn test_parse_polygon_element_space_separated_coordinates() {
        let line = r#"<polygon points="0 0 10 0 5 10" />"#;
        let result = parse_polygon_element(line);

        match result {
            Some(SvgElement::Polygon { points }) => {
                assert_eq!(points, "0 0 10 0 5 10");
            }
            _ => panic!("Expected Some(Polygon)"),
        }
    }
}
