package com.auction;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opencv.core.Core;

import java.io.File;
import java.sql.SQLException;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Test case for TroostwijkScraper that verifies auction discovery and data persistence.
 * Uses a temporary test database to verify that:
 * 1. Dutch auctions are correctly discovered from the live page
 * 2. Auction properties (sale IDs, titles, etc.) are valid
 * 3. Data is correctly persisted to the database
 */
public class TroostwijkScraperTest {

    private TroostwijkScraper scraper;
    private String testDatabasePath;

    @BeforeAll
    public static void loadOpenCV() {
        // Load native OpenCV library before any tests run
        try {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
            System.out.println("✓ OpenCV native library loaded successfully");
        } catch (UnsatisfiedLinkError e) {
            System.err.println("⚠️  Warning: Could not load OpenCV native library");
            System.err.println("   Tests will run without object detection support");
        }
    }

    @BeforeEach
    public void setUp() throws SQLException, java.io.IOException {
        // Create temporary test database
        testDatabasePath = "test_auctions_" + System.currentTimeMillis() + ".db";

        // Initialize scraper with test database (no YOLO models needed for this test)
        // Using non-existent paths for YOLO files will disable object detection
        scraper = new TroostwijkScraper(
                testDatabasePath,
                "desktop",
                "",
                "nonexistent/yolov4.cfg",
                "nonexistent/yolov4.weights",
                "nonexistent/coco.names"
        );
    }
    
    @AfterEach
    public void tearDown() {
        // Clean up test database
        File dbFile = new File(testDatabasePath);
        if (dbFile.exists()) {
            dbFile.delete();
        }
    }
    
    @Test
    public void testDiscoverDutchAuctions() {
        // Discover auctions from the live page
        List<Integer> auctions = scraper.discoverDutchAuctions();
        
        // Verify that auctions were found
        assertNotNull(auctions, "Auctions list should not be null");
        assertFalse(auctions.isEmpty(), "Should find at least one Dutch auction");
        
        // Verify that all sale IDs are positive integers
        for (Integer saleId : auctions) {
            assertNotNull(saleId, "Sale ID should not be null");
            assertTrue(saleId > 0, "Sale ID should be positive: " + saleId);
        }
        
        // Verify no duplicate sale IDs
        long uniqueCount = auctions.stream().distinct().count();
        assertEquals(auctions.size(), uniqueCount, "All sale IDs should be unique");
        
        System.out.println("✓ Found " + auctions.size() + " unique Dutch auctions");
        System.out.println("✓ Sale IDs: " + auctions);
    }
    
    @Test
    public void testFetchAndPersistAuctionData() throws SQLException {
        // First, discover auctions
        List<Integer> auctions = scraper.discoverDutchAuctions();
        assertFalse(auctions.isEmpty(), "Need at least one auction to test");
        
        // Take the first auction and fetch its lots
        Integer firstSaleId = auctions.getFirst();
        System.out.println("Testing with sale ID: " + firstSaleId);
        
        scraper.fetchLotsForSale(firstSaleId);
        
        // Verify data was persisted to database
        List<TroostwijkScraper.Lot> lotsInDb = scraper.db.getAllLots();
        
        assertNotNull(lotsInDb, "Lots list should not be null");
        assertFalse(lotsInDb.isEmpty(), "Should have persisted at least one lot");
        
        // Verify lot properties
        for (TroostwijkScraper.Lot lot : lotsInDb) {
            assertEquals(firstSaleId.intValue(), lot.saleId, "Lot should belong to the correct sale");
            assertTrue(lot.lotId > 0, "Lot ID should be positive");
            assertNotNull(lot.title, "Lot title should not be null");
            assertFalse(lot.title.isEmpty(), "Lot title should not be empty");
            assertNotNull(lot.url, "Lot URL should not be null");
            assertTrue(lot.url.startsWith("https://"), "Lot URL should be valid");
            assertTrue(lot.currentBid >= 0, "Current bid should be non-negative");
        }
        
        System.out.println("✓ Successfully persisted " + lotsInDb.size() + " lots to database");
        System.out.println("✓ All lot properties are valid");
    }
    
    @Test
    public void testDatabaseSchema() throws SQLException {
        // Verify that the database schema was created correctly
        List<TroostwijkScraper.Lot> lots = scraper.db.getAllLots();
        assertNotNull(lots, "Should be able to query lots table");
        
        int imageCount = scraper.db.getImageCount();
        assertTrue(imageCount >= 0, "Image count should be non-negative");
        
        List<TroostwijkScraper.Lot> activeLots = scraper.db.getActiveLots();
        assertNotNull(activeLots, "Should be able to query active lots");
        
        System.out.println("✓ Database schema is valid and queryable");
    }
    
    @Test
    public void testAuctionProperties() {
        List<Integer> auctions = scraper.discoverDutchAuctions();
        assertFalse(auctions.isEmpty(), "Should find auctions");
        
        // Test that we can fetch data for multiple auctions
        int auctionsToTest = Math.min(2, auctions.size());
        
        for (int i = 0; i < auctionsToTest; i++) {
            Integer saleId = auctions.get(i);
            System.out.println("Testing auction " + (i + 1) + ": " + saleId);
            
            // This should not throw an exception
            assertDoesNotThrow(() -> scraper.fetchLotsForSale(saleId),
                    "Should be able to fetch lots for sale " + saleId);
        }
        
        System.out.println("✓ Successfully tested " + auctionsToTest + " auctions");
    }
}
