package com.yorvana.domain

import com.google.common.truth.Truth.assertThat
import com.yorvana.data.billing.BillingManager
import com.yorvana.data.repository.VehicleRepository
import com.yorvana.domain.model.VehicleWithMeta
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class AppGateTest {
    private val testDispatcher = UnconfinedTestDispatcher()
    private val testScope = TestScope(testDispatcher)

    private val vehiclesFlow = MutableStateFlow<List<VehicleWithMeta>>(emptyList())
    private val premiumFlow = MutableStateFlow(false)
    private val pendingFlow = MutableStateFlow(false)

    private val vehicleRepository = mockk<VehicleRepository>()
    private val billingManager = mockk<BillingManager>()
    private lateinit var appGate: AppGate

    @Before
    fun setUp() {
        every { vehicleRepository.observeVehicles() } returns vehiclesFlow
        every { billingManager.isPremium } returns premiumFlow
        every { billingManager.hasPendingPurchase } returns pendingFlow
        appGate = AppGate(vehicleRepository, billingManager, testScope.backgroundScope)
    }

    // Creates unconfigured mocks used only to populate the list size — no behaviour needed.
    private fun vehicles(count: Int): List<VehicleWithMeta> = List(count) { mockk() }

    @Test
    fun `isReadOnly is false when 0 vehicles and free`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(0)
            premiumFlow.value = false
            assertThat(appGate.isReadOnly.value).isFalse()
        }

    @Test
    fun `isReadOnly is false when 1 vehicle and free`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(1)
            premiumFlow.value = false
            assertThat(appGate.isReadOnly.value).isFalse()
        }

    @Test
    fun `isReadOnly is true when 2 vehicles and free`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(2)
            premiumFlow.value = false
            assertThat(appGate.isReadOnly.value).isTrue()
        }

    @Test
    fun `isReadOnly is false when 0 vehicles and premium`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(0)
            premiumFlow.value = true
            assertThat(appGate.isReadOnly.value).isFalse()
        }

    @Test
    fun `isReadOnly is false when 1 vehicle and premium`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(1)
            premiumFlow.value = true
            assertThat(appGate.isReadOnly.value).isFalse()
        }

    @Test
    fun `isReadOnly is false when 2 vehicles and premium`() =
        testScope.runTest {
            vehiclesFlow.value = vehicles(2)
            premiumFlow.value = true
            assertThat(appGate.isReadOnly.value).isFalse()
        }
}
