package com.flagship.abox.manager.testing.fakes

import com.flagship.abox.manager.domain.DomainError
import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.LoginCredentials
import com.flagship.abox.manager.domain.Password
import com.flagship.abox.manager.domain.ProviderProfileId
import com.flagship.abox.manager.domain.SessionValidity
import com.flagship.abox.manager.domain.Username
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class FakeSessionGatewayTest {
    private val profileId = ProviderProfileId("abox")
    private val credentials = LoginCredentials(Username("demo"), Password("secret"))

    @Test
    fun loginPublishesSessionAndLogoutClearsIt() = runTest {
        val gateway = FakeSessionGateway()

        val result = gateway.login(profileId, credentials)

        assertTrue(result is DomainResult.Success)
        assertEquals(Username("demo"), gateway.observeSession(profileId).first()?.username)

        gateway.logout(profileId)

        assertNull(gateway.observeSession(profileId).first())
    }

    @Test
    fun failedLoginDoesNotCreateSession() = runTest {
        val gateway = FakeSessionGateway().apply {
            failLogin(profileId, DomainError.Authentication(externalCode = "20004"))
        }

        val result = gateway.login(profileId, credentials)

        assertTrue(result is DomainResult.Failure)
        assertNull(gateway.observeSession(profileId).first())
    }

    @Test
    fun validationCanSimulateInvalidToken() = runTest {
        val gateway = FakeSessionGateway().apply {
            setValidationResult(profileId, DomainResult.Success(SessionValidity.INVALID))
        }

        assertEquals(
            DomainResult.Success(SessionValidity.INVALID),
            gateway.validateSession(profileId),
        )
    }
}
