//! Edge case integration tests for CleanedDocument with picture elements.
//!
//! These tests cover specific edge cases and interactions between the cleaner feature
//! and picture parsing that might not be covered in the main integration tests.

#[cfg(all(feature = "cleaner", feature = "picture"))]
mod tests {
    use microformats::extensions::CleanedDocument;
    use microformats_types::{Class, Document, Item, KnownClass, PropertyValue};
    use url::Url;

    fn parse_html_to_document(html: &str, base_url: &Url) -> Result<Document, microformats::Error> {
        microformats::from_html(html, base_url)
    }

    #[test]
    fn test_picture_with_mixed_recognized_unrecognized_classes() -> Result<(), microformats::Error>
    {
        let html = r#"
        <div class="h-entry h-unrecognized-mixin">
            <h1 class="p-name">Mixed Classes Entry</h1>
            <picture class="u-photo">
                <source srcset="/images/mixed-800w.jpg 800w" type="image/jpeg">
                <img src="/images/mixed.jpg" alt="Mixed classes">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;

        // The item should be completely filtered out due to unrecognized mixin
        let unrecognized = document.unrecognized_items();
        assert_eq!(unrecognized.len(), 1);

        let cleaned = document.with_only_known_classes();
        assert!(cleaned.items.is_empty());

        Ok(())
    }

    #[test]
    fn test_picture_in_nested_unrecognized_structure() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Valid Entry with Invalid Nested</h1>
            <picture class="u-photo">
                <img src="/images/valid.jpg" alt="Valid image">
            </picture>
            
            <div class="h-unrecognized-children">
                <picture class="u-photo">
                    <source srcset="/images/nested-800w.jpg 800w" type="image/jpeg">
                    <img src="/images/nested.jpg" alt="Nested in unrecognized">
                </picture>
            </div>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;

        // Should preserve the main entry but filter the nested unrecognized item
        let cleaned = document.with_only_known_classes();
        assert_eq!(cleaned.items.len(), 1);

        let entry = &cleaned.items[0];
        assert!(entry.children.is_empty()); // Nested unrecognized should be filtered

        // The main entry should still have its photo
        assert!(entry.properties.contains_key("photo"));

        Ok(())
    }

    #[test]
    fn test_picture_unrecognized_property_in_recognized_item() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Entry with Unrecognized Property</h1>
            <picture class="u-photo">
                <source srcset="/images/valid-800w.jpg 800w" type="image/jpeg">
                <img src="/images/valid.jpg" alt="Valid photo">
            </picture>
            
            <!-- Unrecognized property name - should be filtered -->
            <picture class="u-unrecognized-property">
                <source srcset="/images/unrecognized-800w.jpg 800w" type="image/jpeg">
                <img src="/images/unrecognized.jpg" alt="Unrecognized property">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should only have recognized properties
        assert!(entry.properties.contains_key("name"));
        assert!(entry.properties.contains_key("photo"));

        // Should not contain unrecognized property
        assert!(!entry.properties.contains_key("unrecognized-property"));

        Ok(())
    }

    #[test]
    fn test_picture_with_no_microformat_classes() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Entry with Non-Microformat Pictures</h1>
            
            <!-- Picture with no microformat class - not relevant to cleaning -->
            <picture class="purely-decorative">
                <source srcset="/images/decorative-800w.jpg 800w" type="image/jpeg">
                <img src="/images/decorative.jpg" alt="Decorative">
            </picture>
            
            <!-- Another non-microformat picture -->
            <picture id="image-1">
                <source srcset="/images/regular-800w.jpg 800w" type="image/jpeg">
                <img src="/images/regular.jpg" alt="Regular image">
            </picture>
            
            <!-- This one should be kept -->
            <picture class="u-photo">
                <source srcset="/images/microformat-800w.jpg 800w" type="image/jpeg">
                <img src="/images/microformat.jpg" alt="Microformat image">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should only have the u-photo property
        assert!(entry.properties.contains_key("name"));
        assert!(entry.properties.contains_key("photo"));

        let photos = entry.properties.get("photo").unwrap();
        assert_eq!(photos.len(), 1); // Only the u-photo picture

        Ok(())
    }

    #[test]
    fn test_picture_indeeply_nested_mixed_structure() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-feed">
            <h1 class="p-name">Mixed Structure Feed</h1>
            
            <div class="h-entry">
                <div class="p-author h-card">
                    <picture class="u-photo">
                        <source srcset="/authors/valid-800w.jpg 800w" type="image/jpeg">
                        <img src="/authors/valid.jpg" alt="Valid author">
                    </picture>
                    <div class="h-unrecognized-person">
                        <picture class="u-photo">
                            <img src="/authors/unrecognized.jpg" alt="Unrecognized author">
                        </picture>
                    </div>
                </div>
            </div>
            
            <div class="h-unrecognized-event">
                <div class="h-entry">
                    <picture class="u-photo">
                        <source srcset="/events/nested-valid-800w.jpg 800w" type="image/jpeg">
                        <img src="/events/nested-valid.jpg" alt="Nested valid">
                    </picture>
                </div>
            </div>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let feed = &cleaned.items[0];
        assert!(matches!(&feed.r#type[0], Class::Known(KnownClass::Feed)));

        // Should have one valid h-entry child
        assert_eq!(feed.children.len(), 1);
        let entry = &feed.children[0];
        assert!(matches!(&entry.r#type[0], Class::Known(KnownClass::Entry)));

        // The h-card should be preserved but nested custom person filtered
        if let Some(PropertyValue::Item(author)) = entry.properties.get("author").unwrap().first() {
            assert!(matches!(&author.r#type[0], Class::Known(KnownClass::Card)));
            assert!(author.children.is_empty()); // Unrecognized child filtered
        }

        Ok(())
    }

    #[test]
    fn test_picture_with_relative_urls_and_cleaning() -> Result<(), microformats::Error> {
        let html = r#"
        <article class="h-entry">
            <h1 class="p-name">Relative URLs Test</h1>
            
            <picture class="u-photo">
                <source srcset="images/relative-800w.jpg 800w, ../images/parent-400w.jpg 400w"
                        media="(min-width: 800px)" type="image/jpeg">
                <img src="images/relative.jpg" alt="Relative path image">
            </picture>
        </article>
        
        <div class="h-custom-test">
            <picture class="u-photo">
                <source srcset="custom/custom-800w.jpg 800w" type="image/jpeg">
                <img src="custom/custom.jpg" alt="Custom relative">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://blog.example.com/posts/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Check that URLs were correctly resolved
        if let Some(PropertyValue::Image(image)) = entry.properties.get("photo").unwrap().first() {
            assert_eq!(
                image.value.as_str(),
                "https://blog.example.com/posts/images/relative.jpg"
            );
            assert_eq!(image.alt, Some("Relative path image".to_string()));
        }

        Ok(())
    }

    #[test]
    fn test_picture_with_data_urls_and_cleaning() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Data URL Test</h1>
            
            <picture class="u-photo">
                <source srcset="data:image/jpeg;base64,validbase64data 2x" type="image/jpeg">
                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" alt="Data URL image">
            </picture>
        </div>
        
        <div class="h-custom-data">
            <picture class="u-photo">
                <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Custom data URL">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Data URLs should be preserved as-is
        if let Some(PropertyValue::Image(image)) = entry.properties.get("photo").unwrap().first() {
            assert!(image.value.as_str().starts_with("data:image/png;base64,"));
            assert_eq!(image.alt, Some("Data URL image".to_string()));
        }

        Ok(())
    }

    #[test]
    fn test_picture_with_malformed_attributes_and_cleaning() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Malformed Attributes Test</h1>
            
            <!-- Picture with various malformed attributes -->
            <picture class="u-photo">
                <source srcset="  " media="" type=""> <!-- Empty attributes -->
                <source srcset="  valid.jpg 400w   " media="(min-width: 800px)" type="image/jpeg"> <!-- Whitespace issues -->
                <source srcset="image-without-descriptors.jpg" <!-- No closing quote -->
                <img src="  images/spaces.jpg  " alt="  Whitespace test  "> <!-- Spaces around attributes -->
            </picture>
        </div>
        
        <div class="h-broken-item">
            <picture class="u-photo">
                <source srcset="/broken/malformed.jpg 400w" type="image/jpeg">
                <img src="/broken/fallback.jpg" alt="Should be filtered">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();

        // Should parse successfully despite malformed HTML
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        // Should filter out the broken item and preserve the valid one
        assert_eq!(cleaned.items.len(), 1);

        let entry = &cleaned.items[0];
        assert!(entry.properties.contains_key("photo"));

        Ok(())
    }

    #[test]
    fn test_picture_property_name_edge_cases() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Property Name Edge Cases</h1>
            
            <!-- Edge case: picture with p-name -->
            <picture class="p-name">
                <source srcset="/images/name-source-800w.jpg 800w" type="image/jpeg">
                <img src="/images/name-img.jpg" alt="Picture as name">
            </picture>
            
            <!-- Edge case: picture with u-url -->
            <picture class="u-url">
                <source srcset="/images/url-source-800w.jpg 800w" type="image/jpeg">
                <img src="/images/url-img.jpg" alt="Picture as URL (should use img src)">
            </picture>
            
            <!-- Edge case: picture with dt-published (should not work) -->
            <picture class="dt-published">
                <source srcset="/images/date-source-800w.jpg 800w" type="image/jpeg">
                <img src="/images/date-img.jpg" alt="Picture as date (incorrect)">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should have name from picture
        assert!(entry.properties.contains_key("name"));

        // Should have URL from picture (img src)
        assert!(entry.properties.contains_key("url"));

        // dt-published from picture likely won't work as expected since pictures aren't dates

        Ok(())
    }

    #[test]
    fn test_picture_with_unicode_and_special_chars() -> Result<(), microformats::Error> {
        let html = r#"
        <article class="h-entry">
            <h1 class="p-name">Unicode & Special Characters</h1>
            
            <picture class="u-photo">
                <source srcset="/images/café-800w.jpg 800w" media="(min-width: 800px)" type="image/jpeg">
                <img src="/images/测试.jpg" alt="Test with Unicode: 测试 😊">
            </picture>
            
            <picture class="u-photo">
                <source srcset="/images/special-chars-800w.jpg 800w" type="image/jpeg">
                <img src="/images/special.jpg" alt="Special &amp; chars &quot;quoted&quot;">
            </picture>
        </article>
        
        <div class="h-unicôdé-custom">
            <picture class="u-photo">
                <img src="/images/custom-unicode.jpg" alt="Custom with Unicode">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://unicode.example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should have both photos with Unicode characters preserved
        let photos = entry.properties.get("photo").unwrap();
        assert_eq!(photos.len(), 2);

        // Unicode should be preserved correctly
        for (i, photo) in photos.iter().enumerate() {
            if let PropertyValue::Image(image) = photo {
                let alt = image.alt.as_ref().unwrap_or(&"".to_string());
                println!("Photo {}: alt = '{}'", i + 1, alt);
                // Unicode and special characters should be properly decoded
                assert!(alt.contains("Test") || alt.contains("Special"));
            }
        }

        Ok(())
    }

    #[test]
    fn test_empty_and_minimal_picture_elements() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Empty Picture Tests</h1>
            
            <!-- Empty picture -->
            <picture class="u-photo"></picture>
            
            <!-- Picture with only sources, no img -->
            <picture class="u-logo">
                <source srcset="/images/no-img-source.jpg 400w" type="image/jpeg">
            </picture>
            
            <!-- Picture with only img, no sources -->
            <picture class="u-photo">
                <img src="/images/no-sources.jpg" alt="No sources">
            </picture>
            
            <!-- Picture with empty source -->
            <picture class="u-logo">
                <source srcset="" type="image/jpeg">
                <img src="/images/empty-source.jpg" alt="Empty source">
            </picture>
        </div>
        
        <div class="h-custom-empty">
            <picture class="u-photo">
                <!-- Empty picture in custom item -->
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should have photos and logos from valid picture elements
        assert!(entry.properties.contains_key("photo") || entry.properties.contains_key("logo"));

        Ok(())
    }

    #[test]
    fn test_picture_element_class_combination_edge_cases() -> Result<(), microformats::Error> {
        let html = r#"
        <div class="h-entry">
            <h1 class="p-name">Class Combination Tests</h1>
            
            <!-- Multiple microformat classes on picture -->
            <picture class="u-photo u-logo">
                <source srcset="/images/multi-class-800w.jpg 800w" type="image/jpeg">
                <img src="/images/multi-class.jpg" alt="Multiple classes">
            </picture>
            
            <!-- Mixed microformat and non-microformat classes -->
            <picture class="u-photo decorative styling">
                <source srcset="/images/mixed-800w.jpg 800w" type="image/jpeg">
                <img src="/images/mixed.jpg" alt="Mixed classes">
            </picture>
            
            <!-- Repeated same property class -->
            <picture class="u-photo u-photo">
                <source srcset="/images/duplicate-800w.jpg 800w" type="image/jpeg">
                <img src="/images/duplicate.jpg" alt="Duplicate class">
            </picture>
        </div>
        
        <div class="h-custom-styling">
            <picture class="u-photo custom-class styling-framework">
                <source srcset="/images/custom-styled-800w.jpg 800w" type="image/jpeg">
                <img src="/images/custom-styled.jpg" alt="Custom but styled">
            </picture>
        </div>
        "#;

        let base_url = Url::parse("https://example.com/").unwrap();
        let document = parse_html_to_document(html, &base_url)?;
        let cleaned = document.with_only_known_classes();

        assert_eq!(cleaned.items.len(), 1);
        let entry = &cleaned.items[0];

        // Should handle class combinations appropriately
        assert!(entry.properties.contains_key("photo"));

        Ok(())
    }

    #[test]
    fn testPictureDocumentCleaningStatePreservation() -> Result<(), microformats::Error> {
        let html = r#"
        <!DOCTYPE html>
        <html lang="fr">
        <head>
            <title>Test Document</title>
            <link rel="author" href="https://author.example.com">
        </head>
        <body>
            <article class="h-entry" id="test-entry">
                <h1 class="p-name">State Preservation Test</h1>
                
                <picture class="u-photo">
                    <source srcset="/images/test-800w.jpg 800w" type="image/jpeg">
                    <img src="/images/test.jpg" alt="Test image">
                </picture>
                
                <div class="p-author h-card">
                    <picture class="u-photo">
                        <img src="/images/author.jpg" alt="Test author">
                    </picture>
                    <span class="p-name">Test Author</span>
                </div>
            </article>
            
            <div class="h-custom-content">
                <picture class="u-photo">
                    <img src="/images/custom.jpg" alt="Custom content">
                </picture>
            </div>
        </body>
        </html>
        "#;

        let base_url = Url::parse("https://test.example.com/").unwrap();
        let mut original_doc = parse_html_to_document(html, &base_url)?;

        // Set some additional metadata
        original_doc.lang = Some("fr".to_string());

        // Clean the document
        let cleaned_doc = original_doc.with_only_known_classes();

        // Verify document state is preserved
        assert_eq!(cleaned_doc.lang, Some("fr".to_string()));
        assert_eq!(cleaned_doc.url, Some(base_url));

        // Verify relations are preserved
        assert!(cleaned_doc.rels.items.len() >= 1);

        // Verify items are correctly filtered
        assert_eq!(cleaned_doc.items.len(), 1); // Only h-entry (h-custom-content filtered)

        let entry = &cleaned_doc.items[0];
        assert_eq!(entry.id, Some("test-entry".to_string()));

        // Verify nested structure is preserved
        if let Some(PropertyValue::Item(author)) = entry.properties.get("author").unwrap().first() {
            assert!(author.properties.contains_key("photo"));
            assert!(author.properties.contains_key("name"));
        }

        Ok(())
    }
}
