package app.closer.data.repository

import app.closer.data.remote.FirestoreDateMatchDataSource
import app.closer.data.remote.FirestoreDateSwipeDataSource
import app.closer.domain.model.DateSwipe
import app.closer.domain.model.SwipeAction
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.slot
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class DateMatchRepositoryImplTest {

    private val swipeDataSource: FirestoreDateSwipeDataSource = mockk(relaxed = true)
    private val matchDataSource: FirestoreDateMatchDataSource = mockk(relaxed = true)
    private val repository = DateMatchRepositoryImpl(swipeDataSource, matchDataSource)

    @Test
    fun `recordSwipe records via data source and always returns null match`() = runTest {
        val swipeSlot = slot<DateSwipe>()
        coEvery { swipeDataSource.recordSwipe("couple1", capture(swipeSlot)) } returns Unit

        val result = repository.recordSwipe("couple1", "userA", "idea42", SwipeAction.LOVE)

        assertTrue(result.isSuccess)
        // Match creation is server-side; the client call always returns null.
        assertNull(result.getOrNull())
        coVerify(exactly = 1) { swipeDataSource.recordSwipe("couple1", any()) }
        assertTrue(swipeSlot.captured.userId == "userA")
        assertTrue(swipeSlot.captured.dateIdeaId == "idea42")
        assertTrue(swipeSlot.captured.action == SwipeAction.LOVE)
    }

    @Test
    fun `recordSwipe with SKIP still records and returns null`() = runTest {
        val result = repository.recordSwipe("couple1", "userA", "idea1", SwipeAction.SKIP)
        assertTrue(result.isSuccess)
        assertNull(result.getOrNull())
        coVerify(exactly = 1) { swipeDataSource.recordSwipe(any(), any()) }
    }

    @Test
    fun `recordSwipe propagates data source failure as Result failure`() = runTest {
        coEvery { swipeDataSource.recordSwipe(any(), any()) } throws RuntimeException("Firestore unavailable")

        val result = repository.recordSwipe("couple1", "userA", "idea1", SwipeAction.LOVE)

        assertTrue(result.isFailure)
        assertTrue(result.exceptionOrNull() is RuntimeException)
    }

    @Test
    fun `getDateIdeas returns non-empty seed catalog with valid ids`() = runTest {
        val ideas = repository.getDateIdeas()
        assertTrue("Seed catalog must not be empty", ideas.isNotEmpty())
        assertTrue("All ideas must have non-blank ids", ideas.all { it.id.isNotBlank() })
    }
}
