package com.rssuper.database

import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import com.rssuper.database.daos.SubscriptionDao
import com.rssuper.database.entities.SubscriptionEntity
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import java.util.Date

class SubscriptionDaoTest {
    
    private lateinit var database: RssDatabase
    private lateinit var dao: SubscriptionDao
    
    @Before
    fun createDb() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        database = Room.inMemoryDatabaseBuilder(
            context,
            RssDatabase::class.java
        )
            .allowMainThreadQueries()
            .build()
        dao = database.subscriptionDao()
    }
    
    @After
    fun closeDb() {
        database.close()
    }
    
    @Test
    fun insertAndGetSubscription() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        
        val result = dao.getSubscriptionById("1")
        assertNotNull(result)
        assertEquals("1", result?.id)
        assertEquals("Test Feed", result?.title)
    }
    
    @Test
    fun getSubscriptionByUrl() = runTest {
        val subscription = createTestSubscription("1", url = "https://example.com/feed")
        
        dao.insertSubscription(subscription)
        
        val result = dao.getSubscriptionByUrl("https://example.com/feed")
        assertNotNull(result)
        assertEquals("1", result?.id)
    }
    
    @Test
    fun getAllSubscriptions() = runTest {
        val subscription1 = createTestSubscription("1")
        val subscription2 = createTestSubscription("2")
        
        dao.insertSubscriptions(listOf(subscription1, subscription2))
        
        val result = dao.getAllSubscriptions().first()
        assertEquals(2, result.size)
    }
    
    @Test
    fun getEnabledSubscriptions() = runTest {
        val enabled = createTestSubscription("1", enabled = true)
        val disabled = createTestSubscription("2", enabled = false)
        
        dao.insertSubscriptions(listOf(enabled, disabled))
        
        val result = dao.getEnabledSubscriptions().first()
        assertEquals(1, result.size)
        assertEquals("1", result[0].id)
    }
    
    @Test
    fun updateSubscription() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        
        val updated = subscription.copy(title = "Updated Title")
        dao.updateSubscription(updated)
        
        val result = dao.getSubscriptionById("1")
        assertEquals("Updated Title", result?.title)
    }
    
    @Test
    fun deleteSubscription() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        dao.deleteSubscription(subscription)
        
        val result = dao.getSubscriptionById("1")
        assertNull(result)
    }
    
    @Test
    fun deleteSubscriptionById() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        dao.deleteSubscriptionById("1")
        
        val result = dao.getSubscriptionById("1")
        assertNull(result)
    }
    
    @Test
    fun getSubscriptionCount() = runTest {
        val subscription1 = createTestSubscription("1")
        val subscription2 = createTestSubscription("2")
        
        dao.insertSubscriptions(listOf(subscription1, subscription2))
        
        val count = dao.getSubscriptionCount().first()
        assertEquals(2, count)
    }
    
    @Test
    fun updateError() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        dao.updateError("1", "Feed not found")
        
        val result = dao.getSubscriptionById("1")
        assertEquals("Feed not found", result?.error)
    }
    
    @Test
    fun updateLastFetchedAt() = runTest {
        val subscription = createTestSubscription("1")
        val now = Date()
        
        dao.insertSubscription(subscription)
        dao.updateLastFetchedAt("1", now)
        
        val result = dao.getSubscriptionById("1")
        assertEquals(now, result?.lastFetchedAt)
        assertNull(result?.error)
    }
    
    @Test
    fun updateNextFetchAt() = runTest {
        val subscription = createTestSubscription("1")
        val future = Date(System.currentTimeMillis() + 3600000)
        
        dao.insertSubscription(subscription)
        dao.updateNextFetchAt("1", future)
        
        val result = dao.getSubscriptionById("1")
        assertEquals(future, result?.nextFetchAt)
    }
    
    @Test
    fun insertSubscriptionWithConflict() = runTest {
        val subscription = createTestSubscription("1")
        
        dao.insertSubscription(subscription)
        
        val updated = subscription.copy(title = "Updated")
        dao.insertSubscription(updated)
        
        val result = dao.getSubscriptionById("1")
        assertEquals("Updated", result?.title)
    }
    
    private fun createTestSubscription(
        id: String,
        url: String = "https://example.com/feed/$id",
        title: String = "Test Feed",
        enabled: Boolean = true
    ): SubscriptionEntity {
        val now = Date()
        return SubscriptionEntity(
            id = id,
            url = url,
            title = title,
            category = "Tech",
            enabled = enabled,
            fetchInterval = 3600000,
            createdAt = now,
            updatedAt = now,
            lastFetchedAt = null,
            nextFetchAt = null,
            error = null,
            httpAuthUsername = null,
            httpAuthPassword = null
        )
    }
}
