package com.crm.chat.ui.auth

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.crm.chat.data.AppConstants
import com.crm.chat.data.api.ApiClient
import com.crm.chat.data.api.AuthApiService
import com.crm.chat.data.model.AuthResponse
import com.crm.chat.data.repository.AuthRepository
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class AuthViewModelTest {

    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    private lateinit var authApiService: AuthApiService
    private lateinit var apiClient: ApiClient
    private lateinit var authRepository: AuthRepository
    private lateinit var authViewModel: AuthViewModel

    private val testDispatcher = StandardTestDispatcher()

    @Before
    fun setup() {
        Dispatchers.setMain(testDispatcher)
        
        authApiService = mockk()
        apiClient = mockk()
        coEvery { apiClient.authApiService } returns authApiService
        authRepository = AuthRepository(apiClient)
        authViewModel = AuthViewModel()
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `login returns success when valid credentials provided`() = runTest {
        // Given
        val validToken = "valid-jwt-token"
        val authResponse = AuthResponse(token = validToken)
        val response = retrofit2.Response.success(authResponse)
        
        coEvery { 
            authApiService.loginSite(any()) 
        } returns response

        // When
        authViewModel.login("test@example.com", "password")

        // Then
        val state = authViewModel.loginState.value
        assertTrue(state is AuthViewModel.LoginState.Success)
        val successState = state as AuthViewModel.LoginState.Success
        assertEquals(validToken, successState.authResponse.token)
        assertEquals(AppConstants.SERVER_URL, successState.serverUrl)
    }

    @Test
    fun `login returns error when email is empty`() = runTest {
        // When
        authViewModel.login("", "password")

        // Then
        val state = authViewModel.loginState.value
        assertTrue(state is AuthViewModel.LoginState.Error)
        val errorState = state as AuthViewModel.LoginState.Error
        assertEquals("Электронная почта обязательна для авторизации", errorState.message)
    }

    @Test
    fun `login returns error when password is empty`() = runTest {
        // When
        authViewModel.login("test@example.com", "")

        // Then
        val state = authViewModel.loginState.value
        assertTrue(state is AuthViewModel.LoginState.Error)
        val errorState = state as AuthViewModel.LoginState.Error
        assertEquals("Пароль обязателен для авторизации", errorState.message)
    }

    @Test
    fun `login returns error when server returns empty token`() = runTest {
        // Given
        val authResponse = AuthResponse(token = null)
        val response = retrofit2.Response.success(authResponse)
        
        coEvery { 
            authApiService.loginSite(any()) 
        } returns response

        // When
        authViewModel.login("test@example.com", "password")

        // Then
        val state = authViewModel.loginState.value
        assertTrue(state is AuthViewModel.LoginState.Error)
        val errorState = state as AuthViewModel.LoginState.Error
        assertEquals("Сервер вернул пустой токен. Проверьте правильность email и пароля.", errorState.message)
    }

    @Test
    fun `login returns error when network exception occurs`() = runTest {
        // Given
        coEvery { 
            authApiService.loginSite(any()) 
        } throws java.net.UnknownHostException("Host not found")

        // When
        authViewModel.login("test@example.com", "password")

        // Then
        val state = authViewModel.loginState.value
        assertTrue(state is AuthViewModel.LoginState.Error)
        val errorState = state as AuthViewModel.LoginState.Error
        assertEquals("Неожиданная ошибка: Host not found. Попробуйте перезапустить приложение.", errorState.message)
    }
}
