/*
 * DatabaseTests.vala
 * 
 * Unit tests for database layer.
 */

public class RSSuper.DatabaseTests {
    private Database? db;
    private string test_db_path;
    
    public void run_subscription_crud() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var store = new SubscriptionStore(db);
            
            // Create test subscription
            var subscription = new FeedSubscription.with_values(
                "sub_1",
                "https://example.com/feed.xml",
                "Example Feed",
                60,
                "Technology",
                true,
                "2024-01-01T00:00:00Z",
                "2024-01-01T00:00:00Z"
            );
            
            // Test add
            store.add(subscription);
            var retrieved = store.get_by_id("sub_1");
            if (retrieved == null) {
                printerr("FAIL: Expected subscription to exist after add\n");
                return;
            }
            
            // Test get
            if (retrieved.title != "Example Feed") {
                printerr("FAIL: Expected title 'Example Feed', got '%s'\n", retrieved.title);
                return;
            }
            if (retrieved.url != "https://example.com/feed.xml") {
                printerr("FAIL: Expected url 'https://example.com/feed.xml', got '%s'\n", retrieved.url);
                return;
            }
            
            // Test update
            retrieved.title = "Updated Feed";
            store.update(retrieved);
            var updated = store.get_by_id("sub_1");
            if (updated.title != "Updated Feed") {
                printerr("FAIL: Expected title 'Updated Feed', got '%s'\n", updated.title);
                return;
            }
            
            // Test delete
            store.remove_subscription("sub_1");
            var deleted = store.get_by_id("sub_1");
            if (deleted != null) {
                printerr("FAIL: Expected subscription to be deleted\n");
                return;
            }
            
            print("PASS: test_subscription_crud\n");
        } finally {
            cleanup();
        }
    }
    
    public void run_subscription_list() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var store = new SubscriptionStore(db);
            
            // Add multiple subscriptions
            var sub1 = new FeedSubscription.with_values("sub_1", "https://feed1.com", "Feed 1");
            var sub2 = new FeedSubscription.with_values("sub_2", "https://feed2.com", "Feed 2");
            var sub3 = new FeedSubscription.with_values("sub_3", "https://feed3.com", "Feed 3", 60, null, false);
            
            store.add(sub1);
            store.add(sub2);
            store.add(sub3);
            
            // Test get_all
            var all = store.get_all();
            if (all.length != 3) {
                printerr("FAIL: Expected 3 subscriptions, got %d\n", all.length);
                return;
            }
            
            // Test get_enabled
            var enabled = store.get_enabled();
            if (enabled.length != 2) {
                printerr("FAIL: Expected 2 enabled subscriptions, got %d\n", enabled.length);
                return;
            }
            
            print("PASS: test_subscription_list\n");
        } finally {
            cleanup();
        }
    }
    
    public void run_feed_item_crud() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var sub_store = new SubscriptionStore(db);
            var item_store = new FeedItemStore(db);
            
            // Create subscription first
            var subscription = new FeedSubscription.with_values(
                "sub_1", "https://example.com/feed.xml", "Example Feed"
            );
            sub_store.add(subscription);
            
            // Create test item
            var item = new FeedItem.with_values(
                "item_1",
                "Test Article",
                "https://example.com/article",
                "This is a test description",
                "Full content of the article",
                "John Doe",
                "2024-01-01T12:00:00Z",
                "2024-01-01T12:00:00Z",
                {"Technology", "News"},
                null, null, null, null,
                "sub_1"  // subscription_id (stored as subscription_title in DB)
            );
            
            // Test add
            item_store.add(item);
            var retrieved = item_store.get_by_id("item_1");
            if (retrieved == null) {
                printerr("FAIL: Expected item to exist after add\n");
                return;
            }
            if (retrieved.title != "Test Article") {
                printerr("FAIL: Expected title 'Test Article', got '%s'\n", retrieved.title);
                return;
            }
            
            // Test get by subscription
            var items = item_store.get_by_subscription("sub_1");
            if (items.length != 1) {
                printerr("FAIL: Expected 1 item, got %d\n", items.length);
                return;
            }
            
            // Test mark as read
            item_store.mark_as_read("item_1");
            
            // Test delete
            item_store.delete("item_1");
            var deleted = item_store.get_by_id("item_1");
            if (deleted != null) {
                printerr("FAIL: Expected item to be deleted\n");
                return;
            }
            
            print("PASS: test_feed_item_crud\n");
        } finally {
            cleanup();
        }
    }
    
    public void run_feed_item_batch() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var sub_store = new SubscriptionStore(db);
            var item_store = new FeedItemStore(db);
            
            // Create subscription
            var subscription = new FeedSubscription.with_values(
                "sub_1", "https://example.com/feed.xml", "Example Feed"
            );
            sub_store.add(subscription);
            
            // Create multiple items
            var items = new FeedItem[5];
            for (var i = 0; i < 5; i++) {
                items[i] = new FeedItem.with_values(
                    "item_%d".printf(i),
                    "Article %d".printf(i),
                    "https://example.com/article%d".printf(i),
                    "Description %d".printf(i),
                    null,
                    "Author %d".printf(i),
                    "2024-01-%02dT12:00:00Z".printf(i + 1),
                    null,
                    null,
                    null, null, null, null,
                    "sub_1"  // subscription_id
                );
            }
            
            // Test batch insert
            item_store.add_batch(items);
            
            var all = item_store.get_by_subscription("sub_1");
            if (all.length != 5) {
                printerr("FAIL: Expected 5 items, got %d\n", all.length);
                return;
            }
            
            print("PASS: test_feed_item_batch\n");
        } finally {
            cleanup();
        }
    }
    
    public void run_search_history() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var store = new SearchHistoryStore(db);
            
            // Create test queries
            var query1 = SearchQuery("test query", 1, 20, null, SearchSortOption.RELEVANCE);
            var query2 = SearchQuery("another search", 1, 10, null, SearchSortOption.DATE_DESC);
            
            // Test record
            store.record_search(query1, 15);
            store.record_search(query2, 8);
            
            // Test get_history
            var history = store.get_history();
            if (history.length != 2) {
                printerr("FAIL: Expected 2 history entries, got %d\n", history.length);
                return;
            }
            // Check that both queries are in history (order may vary due to timing)
            bool found_test_query = false;
            bool found_another_search = false;
            foreach (var q in history) {
                if (q.query == "test query") found_test_query = true;
                if (q.query == "another search") found_another_search = true;
            }
            if (!found_test_query || !found_another_search) {
                printerr("FAIL: Expected both queries in history\n");
                return;
            }
            
            // Test get_recent
            var recent = store.get_recent();
            if (recent.length != 2) {
                printerr("FAIL: Expected 2 recent entries, got %d\n", recent.length);
                return;
            }
            
            print("PASS: test_search_history\n");
        } finally {
            cleanup();
        }
    }
    
    public void run_fts_search() {
        try {
            test_db_path = "/tmp/rssuper_test_%d.db".printf((int)new DateTime.now_local().to_unix());
            db = new Database(test_db_path);
        } catch (DBError e) {
            warning("Failed to create test database: %s", e.message);
            return;
        }
        
        try {
            var sub_store = new SubscriptionStore(db);
            var item_store = new FeedItemStore(db);
            
            // Create subscription
            var subscription = new FeedSubscription.with_values(
                "sub_1", "https://example.com/feed.xml", "Example Feed"
            );
            sub_store.add(subscription);
            
            // Add items with searchable content
            var item1 = new FeedItem.with_values(
                "item_1",
                "Swift Programming Guide",
                "https://example.com/swift",
                "Learn Swift programming language basics",
                "A comprehensive guide to Swift",
                "Apple Developer",
                "2024-01-01T12:00:00Z",
                null,
                null,
                null, null, null, null,
                "sub_1"  // subscription_id
            );
            
            var item2 = new FeedItem.with_values(
                "item_2",
                "Python for Data Science",
                "https://example.com/python",
                "Data analysis with Python and pandas",
                "Complete Python data science tutorial",
                "Data Team",
                "2024-01-02T12:00:00Z",
                null,
                null,
                null, null, null, null,
                "sub_1"  // subscription_id
            );
            
            item_store.add(item1);
            item_store.add(item2);
            
            // Test FTS search
            var results = item_store.search("swift");
            if (results.length != 1) {
                printerr("FAIL: Expected 1 result for 'swift', got %d\n", results.length);
                return;
            }
            if (results[0].title != "Swift Programming Guide") {
                printerr("FAIL: Expected 'Swift Programming Guide', got '%s'\n", results[0].title);
                return;
            }
            
            results = item_store.search("python");
            if (results.length != 1) {
                printerr("FAIL: Expected 1 result for 'python', got %d\n", results.length);
                return;
            }
            if (results[0].title != "Python for Data Science") {
                printerr("FAIL: Expected 'Python for Data Science', got '%s'\n", results[0].title);
                return;
            }
            
            print("PASS: test_fts_search\n");
        } finally {
            cleanup();
        }
    }
    
    private void cleanup() {
        if (db != null) {
            db.close();
            db = null;
        }
        
        // Clean up test database
        if (test_db_path != null && test_db_path.length > 0) {
            var file = File.new_for_path(test_db_path);
            if (file.query_exists()) {
                try {
                    file.delete();
                } catch (Error e) {
                    warning("Failed to delete test database: %s", e.message);
                }
            }
            
            // Clean up WAL file
            var wal_file = File.new_for_path(test_db_path + "-wal");
            if (wal_file.query_exists()) {
                try {
                    wal_file.delete();
                } catch (Error e) {
                    warning("Failed to delete WAL file: %s", e.message);
                }
            }
        }
    }
    
    public static int main(string[] args) {
        print("Running database tests...\n");
        
        var tests = new DatabaseTests();
        
        print("\n=== Running subscription CRUD tests ===");
        tests.run_subscription_crud();
        
        print("\n=== Running subscription list tests ===");
        tests.run_subscription_list();
        
        print("\n=== Running feed item CRUD tests ===");
        tests.run_feed_item_crud();
        
        print("\n=== Running feed item batch tests ===");
        tests.run_feed_item_batch();
        
        print("\n=== Running search history tests ===");
        tests.run_search_history();
        
        print("\n=== Running FTS search tests ===");
        tests.run_fts_search();
        
        print("\nAll tests completed!\n");
        return 0;
    }
}
