#![cfg(all(feature = "image", feature = "svg"))]

use pdfmake_rust::{Document, DocumentNode, ImageNode, PdfMake, SvgNode};

fn decompress_pdf_content(pdf: &[u8]) -> String {
    use flate2::read::ZlibDecoder;
    use std::io::Read;
    let mut result = String::new();
    let mut pos = 0usize;
    while let Some(stream_start) = pdf[pos..]
        .windows(8)
        .position(|w| w == b"\nstream\n" || w == b"\rstream\n")
    {
        let abs_start = pos + stream_start;
        let data_start = abs_start + 8;
        let remaining = &pdf[data_start..];
        let end_marker_pos = remaining
            .windows(10)
            .position(|w| w == b"\nendstream" || w == b"\rendstream");
        let data_end = match end_marker_pos {
            Some(p) => data_start + p,
            None => data_start + remaining.len(),
        };
        if data_end > data_start {
            let compressed = &pdf[data_start..data_end];
            let mut decoder = ZlibDecoder::new(compressed);
            let mut decompressed = String::new();
            if decoder.read_to_string(&mut decompressed).is_ok() {
                if !decompressed.is_empty() {
                    result.push_str(&decompressed);
                }
            }
        }
        pos = data_end + 10;
    }
    result
}

#[test]
fn image_with_link_creates_annotation() {
    let document = Document::builder()
        .content(DocumentNode::image(
            ImageNode::bytes(minimal_png_2x1())
                .width(100.0)
                .link("https://example.com"),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    assert!(pdf.starts_with(b"%PDF"));

    let pdf_str = String::from_utf8_lossy(&pdf);
    assert!(
        pdf_str.contains("/Subtype /Link"),
        "PDF should contain Link annotation"
    );
    assert!(
        pdf_str.contains("https://example.com"),
        "PDF should contain the URL"
    );
}

#[test]
fn image_with_link_to_destination_creates_annotation() {
    let document = Document::builder()
        .content(DocumentNode::image(
            ImageNode::bytes(minimal_png_2x1())
                .width(100.0)
                .link_to_destination("my_dest"),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    let pdf_str = String::from_utf8_lossy(&pdf);
    assert!(
        pdf_str.contains("/Dest (my_dest)"),
        "PDF should contain destination annotation"
    );
}

#[test]
fn svg_with_link_creates_annotation() {
    let svg_markup = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect x="10" y="10" width="80" height="80" fill="blue"/></svg>"#;
    let document = Document::builder()
        .content(DocumentNode::svg(
            SvgNode::new(svg_markup)
                .width(100.0)
                .height(100.0)
                .link("https://example.com/svg"),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    let pdf_str = String::from_utf8_lossy(&pdf);
    assert!(
        pdf_str.contains("/Subtype /Link"),
        "PDF should contain Link annotation for SVG"
    );
    assert!(
        pdf_str.contains("https://example.com/svg"),
        "PDF should contain the SVG URL"
    );
}

#[test]
fn svg_with_link_to_page_creates_annotation() {
    let svg_markup = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect x="10" y="10" width="80" height="80" fill="red"/></svg>"#;
    let document = Document::builder()
        .content(DocumentNode::svg(
            SvgNode::new(svg_markup)
                .width(100.0)
                .height(100.0)
                .link_to_page(2),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    let pdf_str = String::from_utf8_lossy(&pdf);
    assert!(
        pdf_str.contains("/Subtype /Link"),
        "PDF should contain Link annotation for SVG page link"
    );
}

#[test]
fn image_link_to_page_registers_named_destination() {
    use pdfmake_rust::{PageSize, Margins};

    let long_text = "word ".repeat(500);
    let document = Document::builder()
        .page_size(PageSize::new(200.0, 150.0))
        .page_margins(Margins::all(10.0))
        .content(DocumentNode::text(&long_text))
        .content(DocumentNode::image(
            ImageNode::bytes(minimal_png_2x1())
                .width(50.0)
                .link_to_page(1),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    let pdf_str = String::from_utf8_lossy(&pdf);
    assert!(
        pdf_str.contains("/Subtype /Link"),
        "PDF should contain Link annotation"
    );
    assert!(
        pdf_str.contains("(__page_1)"),
        "PDF catalog should contain __page_1 named destination"
    );
}

#[test]
fn image_without_link_has_no_annotation() {
    let document = Document::builder()
        .content(DocumentNode::image(
            ImageNode::bytes(minimal_png_2x1()).width(100.0),
        ))
        .build();

    let pdf = PdfMake::new().render(&document).unwrap();
    assert!(pdf.starts_with(b"%PDF"));
}

#[test]
fn image_link_builder_methods_work() {
    let img = ImageNode::path("test.png")
        .link("https://example.com")
        .link_to_page(5)
        .link_to_destination("chapter1");

    assert_eq!(img.link, Some("https://example.com".to_string()));
    assert_eq!(img.link_to_page, Some(5));
    assert_eq!(
        img.link_to_destination,
        Some("chapter1".to_string())
    );
}

#[test]
fn svg_link_builder_methods_work() {
    let svg = SvgNode::new("<svg/>")
        .link("https://example.com")
        .link_to_page(3)
        .link_to_destination("section2");

    assert_eq!(svg.link, Some("https://example.com".to_string()));
    assert_eq!(svg.link_to_page, Some(3));
    assert_eq!(
        svg.link_to_destination,
        Some("section2".to_string())
    );
}

fn minimal_png_2x1() -> Vec<u8> {
    vec![
        137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 2, 0, 0, 0, 1,
        8, 2, 0, 0, 0, 0, 0, 0, 0,
    ]
}
