#![cfg(feature = "svg")]

use pdfmake_rust::{Document, DocumentNode, FontRegistry, SvgNode};

#[test]
fn document_accepts_svg_node_with_raw_markup() {
    let markup = r#"<svg width="100" height="40"><rect x="0" y="0" width="100" height="40"/></svg>"#;
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(markup).width(80.0)))
        .build();

    match &document.content[0] {
        DocumentNode::Svg(svg) => {
            assert_eq!(svg.markup, markup);
            assert_eq!(svg.width, Some(80.0));
            assert_eq!(svg.height, None);
        }
        other => panic!("expected svg node, got {other:?}"),
    }
}

use pdfmake_rust::{normalize_document, Alignment};

#[test]
fn normalize_preserves_svg_block_fields() {
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(r#"<svg width="100" height="40"></svg>"#).height(20.0).alignment(Alignment::Center)))
        .build();

    let normalized = normalize_document(&document).unwrap();
    match &normalized.blocks[0] {
        pdfmake_rust::NormalizedBlock::Svg(svg) => {
            assert_eq!(svg.height, Some(20.0));
            assert_eq!(svg.alignment, Alignment::Center);
        }
        other => panic!("expected normalized svg, got {other:?}"),
    }
}

use pdfmake_rust::{measure_document, PdfMakeError};

#[test]
fn measure_svg_parses_dimensions_and_rect_shape() {
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(r#"<svg width="100" height="40"><rect x="10" y="5" width="30" height="20"/></svg>"#).width(50.0)))
        .build();

    let normalized = normalize_document(&document).unwrap();
    let measured = measure_document(&normalized, &FontRegistry::empty()).unwrap();

    match &measured.blocks[0] {
        pdfmake_rust::MeasuredBlock::Svg(svg) => {
            assert_eq!(svg.width, 50.0);
            assert_eq!(svg.height, 20.0);
            assert_eq!(svg.view_width, 100.0);
            assert_eq!(svg.view_height, 40.0);
            assert_eq!(svg.shapes.len(), 1);
        }
        other => panic!("expected measured svg, got {other:?}"),
    }
}

#[test]
fn measure_svg_reports_unsupported_element() {
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(r#"<svg width="100" height="40"><text>hello</text></svg>"#)))
        .build();

    let normalized = normalize_document(&document).unwrap();
    let error = measure_document(&normalized, &FontRegistry::empty()).unwrap_err();
    match error {
        PdfMakeError::UnsupportedSvgElement(element) => assert_eq!(element, "text"),
        other => panic!("expected unsupported svg element, got {other:?}"),
    }
}

use pdfmake_rust::{layout_document, PdfMake};

#[test]
fn layout_svg_creates_svg_item() {
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(r#"<svg width="100" height="40"><rect width="100" height="40"/></svg>"#)))
        .build();
    let normalized = normalize_document(&document).unwrap();
    let measured = measure_document(&normalized, &FontRegistry::empty()).unwrap();
    let layout = layout_document(&measured).unwrap();

    match &layout.pages[0].items[0] {
        pdfmake_rust::LayoutItem::Svg(svg) => {
            assert_eq!(svg.width, 100.0);
            assert_eq!(svg.height, 40.0);
            assert_eq!(svg.shapes.len(), 1);
        }
        other => panic!("expected layout svg, got {other:?}"),
    }
}

#[test]
fn render_svg_document_outputs_vector_operators() {
    let document = Document::builder()
        .content(DocumentNode::svg(SvgNode::new(r#"<svg width="100" height="40"><rect x="0" y="0" width="100" height="40"/><line x1="0" y1="0" x2="100" y2="40"/></svg>"#)))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    let text = String::from_utf8_lossy(&pdf);

    assert!(text.contains("/Filter /FlateDecode"));
    assert!(text.contains("stream\n"));
    assert!(text.contains("endstream"));
    assert!(!text.contains("/Subtype /Image"));
}

#[test]
fn svg_path_basic_line_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="100" height="100"><path d="M 10 10 L 90 90" stroke="red" stroke-width="2"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_path_closed_shape_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="100" height="100"><path d="M 10 10 L 90 10 L 90 90 Z" fill="blue"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_path_curves_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="100" height="100"><path d="M 10 80 C 40 10, 65 10, 90 80" stroke="green" fill="none"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_path_quadratic_curves_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="100" height="100"><path d="M 10 80 Q 50 10 90 80" stroke="purple" fill="none"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_path_relative_commands_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="100" height="100"><path d="M 10 10 l 80 0 l 0 80 Z" fill="orange"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_ellipse_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r##"<svg width="200" height="100"><ellipse cx="100" cy="50" rx="80" ry="40" fill="#3498db" stroke="#2c3e50" stroke-width="2"/></svg>"##)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_polyline_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="200" height="100"><polyline points="10,10 190,10 190,90 10,90" fill="none" stroke="blue" stroke-width="2"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_polygon_renders() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="200" height="100"><polygon points="100,10 190,90 10,90" fill="red" stroke="black" stroke-width="1"/></svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}

#[test]
fn svg_line_styles_render() {
    let doc = Document::builder()
        .content(DocumentNode::Svg(
            SvgNode::new(r#"<svg width="200" height="100">
                <line x1="10" y1="20" x2="190" y2="20" stroke="red" stroke-width="4" stroke-linecap="round"/>
                <line x1="10" y1="50" x2="190" y2="50" stroke="blue" stroke-width="4" stroke-dasharray="10,5"/>
                <rect x="10" y="70" width="80" height="20" fill="none" stroke="green" stroke-width="3" stroke-linejoin="round"/>
            </svg>"#)
        ))
        .build();
    let pdf = PdfMake::new().render(&doc).unwrap();
    assert!(pdf.len() > 100);
}