/*
 * ParserTests.vala
 * 
 * Unit tests for RSS/Atom feed parser.
 */

public class RSSuper.ParserTests {
    
    public static int main(string[] args) {
        var tests = new ParserTests();
        
        tests.test_rss_parsing();
        tests.test_atom_parsing();
        tests.test_feed_type_detection();
        tests.test_malformed_xml();
        tests.test_itunes_namespace();
        tests.test_enclosures();
        
        print("All parser tests passed!\n");
        return 0;
    }
    
    public void test_rss_parsing() {
        var rss_content = """<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Test Feed</title>
    <link>https://example.com</link>
    <description>A test RSS feed</description>
    <language>en</language>
    <lastBuildDate>Mon, 01 Jan 2024 12:00:00 GMT</lastBuildDate>
    <ttl>60</ttl>
    <item>
      <title>First Post</title>
      <link>https://example.com/post1</link>
      <description>This is the first post</description>
      <pubDate>Mon, 01 Jan 2024 12:00:00 GMT</pubDate>
      <guid>post-1</guid>
    </item>
    <item>
      <title>Second Post</title>
      <link>https://example.com/post2</link>
      <description>This is the second post</description>
      <pubDate>Tue, 02 Jan 2024 12:00:00 GMT</pubDate>
      <guid>post-2</guid>
    </item>
  </channel>
</rss>""";
        
        var parser = new FeedParser();
        var result = parser.parse(rss_content, "https://example.com/feed.xml");
        
        print("RSS parsing result ok: %s\n", result.ok ? "true" : "false");
        
        if (!result.ok) {
            printerr("FAIL: RSS parsing failed: %s\n", result.get_error().message);
            return;
        }
        
        var feed = result.get_value() as Feed;
        if (feed == null) {
            printerr("FAIL: Expected Feed object\n");
            return;
        }
        
        print("Feed title: '%s'\n", feed.title);
        print("Feed link: '%s'\n", feed.link);
        print("Feed description: '%s'\n", feed.description);
        print("Items length: %d\n", feed.items.length);
        
        if (feed.items.length > 0) {
            print("First item title: '%s'\n", feed.items[0].title);
        }
        if (feed.items.length > 1) {
            print("Second item title: '%s'\n", feed.items[1].title);
        }
        
        if (feed.title != "Test Feed") {
            printerr("FAIL: Expected title 'Test Feed', got '%s'\n", feed.title);
            return;
        }
        
        if (feed.link != "https://example.com") {
            printerr("FAIL: Expected link 'https://example.com', got '%s'\n", feed.link);
            return;
        }
        
        if (feed.description != "A test RSS feed") {
            printerr("FAIL: Expected description 'A test RSS feed', got '%s'\n", feed.description);
            return;
        }
        
        if (feed.items.length != 2) {
            printerr("FAIL: Expected 2 items, got %d\n", feed.items.length);
            return;
        }
        
        if (feed.items[0].title != "First Post") {
            printerr("FAIL: Expected first item title 'First Post', got '%s'\n", feed.items[0].title);
            return;
        }
        
        if (feed.items[1].title != "Second Post") {
            printerr("FAIL: Expected second item title 'Second Post', got '%s'\n", feed.items[1].title);
            return;
        }
        
        print("PASS: test_rss_parsing\n");
    }
    
    public void test_atom_parsing() {
        var atom_content = """<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Test Atom Feed</title>
  <subtitle>A test Atom feed</subtitle>
  <link href="https://example.com" rel="alternate"/>
  <link href="https://example.com/feed.xml" rel="self"/>
  <updated>2024-01-01T12:00:00Z</updated>
  <id>urn:uuid:feed-123</id>
  <entry>
    <title>First Entry</title>
    <link href="https://example.com/entry1" rel="alternate"/>
    <summary>This is the first entry</summary>
    <updated>2024-01-01T12:00:00Z</updated>
    <published>2024-01-01T12:00:00Z</published>
    <id>urn:uuid:entry-1</id>
    <author>
      <name>Test Author</name>
    </author>
  </entry>
  <entry>
    <title>Second Entry</title>
    <link href="https://example.com/entry2" rel="alternate"/>
    <summary>This is the second entry</summary>
    <updated>2024-01-02T12:00:00Z</updated>
    <published>2024-01-02T12:00:00Z</published>
    <id>urn:uuid:entry-2</id>
  </entry>
</feed>""";
        
        var parser = new FeedParser();
        var result = parser.parse(atom_content, "https://example.com/feed.xml");
        
        if (!result.ok) {
            printerr("FAIL: Atom parsing failed: %s\n", result.get_error().message);
            return;
        }
        
        var feed = result.get_value() as Feed;
        if (feed == null) {
            printerr("FAIL: Expected Feed object\n");
            return;
        }
        
        if (feed.title != "Test Atom Feed") {
            printerr("FAIL: Expected title 'Test Atom Feed', got '%s'\n", feed.title);
            return;
        }
        
        if (feed.link != "https://example.com") {
            printerr("FAIL: Expected link 'https://example.com', got '%s'\n", feed.link);
            return;
        }
        
        if (feed.subtitle != "A test Atom feed") {
            printerr("FAIL: Expected subtitle 'A test Atom feed', got '%s'\n", feed.subtitle);
            return;
        }
        
        if (feed.items.length != 2) {
            printerr("FAIL: Expected 2 items, got %d\n", feed.items.length);
            return;
        }
        
        if (feed.items[0].title != "First Entry") {
            printerr("FAIL: Expected first item title 'First Entry', got '%s'\n", feed.items[0].title);
            return;
        }
        
        if (feed.items[0].author != "Test Author") {
            printerr("FAIL: Expected first item author 'Test Author', got '%s'\n", feed.items[0].author);
            return;
        }
        
        if (feed.items[0].description != "This is the first entry") {
            printerr("FAIL: Expected first item description 'This is the first entry', got '%s'\n", feed.items[0].description);
            return;
        }
        
        print("PASS: test_atom_parsing\n");
    }
    
    public void test_feed_type_detection() {
        var parser = new FeedParser();
        
        var rss_content = """<?xml version="1.0"?><rss version="2.0"><channel><title>Test</title></channel></rss>""";
        var type = parser.detect_feed_type(rss_content);
        if (type != FeedType.RSS_2_0) {
            printerr("FAIL: Expected RSS 2.0, got %s\n", type.to_string());
            return;
        }
        
        var atom_content = """<?xml version="1.0"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Test</title></feed>""";
        type = parser.detect_feed_type(atom_content);
        if (type != FeedType.ATOM) {
            printerr("FAIL: Expected Atom, got %s\n", type.to_string());
            return;
        }
        
        var rdf_content = """<?xml version="1.0"?><RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><channel><title>Test</title></channel></RDF>""";
        type = parser.detect_feed_type(rdf_content);
        if (type != FeedType.RSS_1_0) {
            printerr("FAIL: Expected RSS 1.0, got %s\n", type.to_string());
            return;
        }
        
        print("PASS: test_feed_type_detection\n");
    }
    
    public void test_malformed_xml() {
        var parser = new FeedParser();
        
        var result = parser.parse("not xml at all", "https://example.com/feed.xml");
        if (result.ok) {
            printerr("FAIL: Expected parsing to fail for malformed XML\n");
            return;
        }
        
        result = parser.parse("<rss><channel>", "https://example.com/feed.xml");
        if (result.ok) {
            printerr("FAIL: Expected parsing to fail for incomplete XML\n");
            return;
        }
        
        print("PASS: test_malformed_xml\n");
    }
    
    public void test_itunes_namespace() {
        var rss_content = """<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
  <channel>
    <title>Podcast Feed</title>
    <link>https://example.com</link>
    <itunes:author>Podcast Author</itunes:author>
    <itunes:summary>A podcast feed</itunes:summary>
    <item>
      <title>Episode 1</title>
      <link>https://example.com/episode1</link>
      <description>Episode summary</description>
      <itunes:author>Episode Author</itunes:author>
      <enclosure url="https://example.com/episode1.mp3" type="audio/mpeg" length="12345678"/>
    </item>
  </channel>
</rss>""";
        
        var parser = new FeedParser();
        var result = parser.parse(rss_content, "https://example.com/feed.xml");
        
        if (!result.ok) {
            printerr("FAIL: iTunes parsing failed: %s\n", result.get_error().message);
            return;
        }
        
        var feed = result.get_value() as Feed;
        if (feed == null) {
            printerr("FAIL: Expected Feed object\n");
            return;
        }
        
        if (feed.items.length != 1) {
            printerr("FAIL: Expected 1 item, got %d\n", feed.items.length);
            return;
        }
        
        if (feed.items[0].author != "Episode Author") {
            printerr("FAIL: Expected author 'Episode Author', got '%s'\n", feed.items[0].author);
            return;
        }
        
        if (feed.items[0].description != "Episode summary") {
            printerr("FAIL: Expected description 'Episode summary', got '%s'\n", feed.items[0].description);
            return;
        }
        
        print("PASS: test_itunes_namespace\n");
    }
    
    public void test_enclosures() {
        var rss_content = """<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Enclosure Test</title>
    <link>https://example.com</link>
    <item>
      <title>Post with Enclosure</title>
      <link>https://example.com/post</link>
      <enclosure url="https://example.com/file.mp3" type="audio/mpeg" length="12345678"/>
    </item>
    <item>
      <title>Post without Enclosure</title>
      <link>https://example.com/post2</link>
    </item>
  </channel>
</rss>""";
        
        var parser = new FeedParser();
        var result = parser.parse(rss_content, "https://example.com/feed.xml");
        
        if (!result.ok) {
            printerr("FAIL: Enclosure parsing failed: %s\n", result.get_error().message);
            return;
        }
        
        var feed = result.get_value() as Feed;
        if (feed == null) {
            printerr("FAIL: Expected Feed object\n");
            return;
        }
        
        if (feed.items.length != 2) {
            printerr("FAIL: Expected 2 items, got %d\n", feed.items.length);
            return;
        }
        
        if (feed.items[0].enclosure_url != "https://example.com/file.mp3") {
            printerr("FAIL: Expected enclosure_url 'https://example.com/file.mp3', got '%s'\n", feed.items[0].enclosure_url);
            return;
        }
        
        if (feed.items[0].enclosure_type != "audio/mpeg") {
            printerr("FAIL: Expected enclosure_type 'audio/mpeg', got '%s'\n", feed.items[0].enclosure_type);
            return;
        }
        
        if (feed.items[0].enclosure_length != "12345678") {
            printerr("FAIL: Expected enclosure_length '12345678', got '%s'\n", feed.items[0].enclosure_length);
            return;
        }
        
        if (feed.items[1].enclosure_url != null) {
            printerr("FAIL: Expected no enclosure for second item\n");
            return;
        }
        
        print("PASS: test_enclosures\n");
    }
}
