package com.swoosh.microblog.data.db

import android.content.Context
import androidx.room.Room
import com.swoosh.microblog.data.model.LocalPost
import com.swoosh.microblog.data.model.PostStatus
import com.swoosh.microblog.data.model.QueueStatus
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28], application = android.app.Application::class)
class LocalPostDaoTest {

    private lateinit var database: AppDatabase
    private lateinit var dao: LocalPostDao

    @Before
    fun setUp() {
        val context: Context = RuntimeEnvironment.getApplication()
        database = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
            .allowMainThreadQueries()
            .build()
        dao = database.localPostDao()
    }

    @After
    fun tearDown() {
        database.close()
    }

    // --- Account-filtered queries ---

    @Test
    fun `getPostsByAccount returns only posts for specified account`() = runTest {
        val post1 = LocalPost(
            accountId = "account-1",
            title = "Post for account 1",
            content = "Content 1"
        )
        val post2 = LocalPost(
            accountId = "account-2",
            title = "Post for account 2",
            content = "Content 2"
        )
        val post3 = LocalPost(
            accountId = "account-1",
            title = "Another post for account 1",
            content = "Content 3"
        )

        dao.insertPost(post1)
        dao.insertPost(post2)
        dao.insertPost(post3)

        val account1Posts = dao.getPostsByAccount("account-1").first()
        assertEquals(2, account1Posts.size)
        assertTrue(account1Posts.all { it.accountId == "account-1" })
    }

    @Test
    fun `getPostsByAccount returns empty list for account with no posts`() = runTest {
        val post = LocalPost(
            accountId = "account-1",
            title = "Post",
            content = "Content"
        )
        dao.insertPost(post)

        val posts = dao.getPostsByAccount("account-2").first()
        assertEquals(0, posts.size)
    }

    @Test
    fun `getAllPosts returns posts from all accounts`() = runTest {
        dao.insertPost(LocalPost(accountId = "account-1", title = "P1", content = "C1"))
        dao.insertPost(LocalPost(accountId = "account-2", title = "P2", content = "C2"))

        val allPosts = dao.getAllPosts().first()
        assertEquals(2, allPosts.size)
    }

    @Test
    fun `getQueuedPostsByAccount returns only queued posts for account`() = runTest {
        dao.insertPost(
            LocalPost(
                accountId = "account-1",
                title = "Queued 1",
                content = "C1",
                queueStatus = QueueStatus.QUEUED_PUBLISH
            )
        )
        dao.insertPost(
            LocalPost(
                accountId = "account-2",
                title = "Queued 2",
                content = "C2",
                queueStatus = QueueStatus.QUEUED_PUBLISH
            )
        )
        dao.insertPost(
            LocalPost(
                accountId = "account-1",
                title = "Not queued",
                content = "C3",
                queueStatus = QueueStatus.NONE
            )
        )

        val queued = dao.getQueuedPostsByAccount("account-1")
        assertEquals(1, queued.size)
        assertEquals("Queued 1", queued[0].title)
    }

    @Test
    fun `getQueuedPosts returns queued posts from all accounts`() = runTest {
        dao.insertPost(
            LocalPost(
                accountId = "account-1",
                title = "Q1",
                content = "C1",
                queueStatus = QueueStatus.QUEUED_PUBLISH
            )
        )
        dao.insertPost(
            LocalPost(
                accountId = "account-2",
                title = "Q2",
                content = "C2",
                queueStatus = QueueStatus.QUEUED_SCHEDULED
            )
        )

        val queued = dao.getQueuedPosts()
        assertEquals(2, queued.size)
    }

    // --- accountId field on LocalPost ---

    @Test
    fun `LocalPost stores and retrieves accountId`() = runTest {
        val id = dao.insertPost(
            LocalPost(
                accountId = "test-account-id",
                title = "Test",
                content = "Content"
            )
        )

        val retrieved = dao.getPostById(id)
        assertNotNull(retrieved)
        assertEquals("test-account-id", retrieved!!.accountId)
    }

    @Test
    fun `LocalPost has empty string as default accountId`() {
        val post = LocalPost(title = "Test", content = "Content")
        assertEquals("", post.accountId)
    }

    @Test
    fun `getPostsByAccount orders by updatedAt descending`() = runTest {
        dao.insertPost(
            LocalPost(
                accountId = "account-1",
                title = "Older",
                content = "C1",
                updatedAt = 1000L
            )
        )
        dao.insertPost(
            LocalPost(
                accountId = "account-1",
                title = "Newer",
                content = "C2",
                updatedAt = 2000L
            )
        )

        val posts = dao.getPostsByAccount("account-1").first()
        assertEquals("Newer", posts[0].title)
        assertEquals("Older", posts[1].title)
    }
}
