package com.crm.chat.data.repository

import com.crm.chat.data.api.ApiClient
import com.crm.chat.data.api.ChatApiService
import com.crm.chat.data.model.*
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import retrofit2.Response

class ChatRepositoryTest {

    private lateinit var chatApiService: ChatApiService
    private lateinit var apiClient: ApiClient
    private lateinit var chatRepository: ChatRepository

    @Before
    fun setup() {
        chatApiService = mockk()
        apiClient = mockk()
        chatRepository = ChatRepository(apiClient)
    }

    @Test
    fun `getChats returns success when server returns valid response`() = runBlocking {
        // Given
        val chat = Chat(
            id = 1L,
            name = "Test Chat",
            type = ChatType.PERSONAL,
            providerId = 1L
        )
        val chatsResponse = ChatsResponse(chats = listOf(chat), totalCount = 1)
        val response = Response.success(chatsResponse)
        
        coEvery { 
            chatApiService.getChats(any(), any()) 
        } returns response

        // When
        val result = chatRepository.getChats()

        // Then
        assertTrue(result.isSuccess)
        assertEquals(1, result.getOrNull()?.chats?.size)
        assertEquals("Test Chat", result.getOrNull()?.chats?.first()?.name)
    }

    @Test
    fun `getChats returns error when server returns error`() = runBlocking {
        // Given
        val response = Response.error<ChatsResponse>(500, mockk())
        
        coEvery { 
            chatApiService.getChats(any(), any()) 
        } returns response

        // When
        val result = chatRepository.getChats()

        // Then
        assertTrue(result.isFailure)
    }

    @Test
    fun `createPersonalChat returns success when server returns valid response`() = runBlocking {
        // Given
        val chat = Chat(
            id = 1L,
            name = "Personal Chat",
            type = ChatType.PERSONAL,
            providerId = 1L
        )
        val response = Response.success(chat)
        val request = CreatePersonalChatRequest(providerId = 1L, companionId = 2L)
        
        coEvery { 
            chatApiService.createPersonalChat(any()) 
        } returns response

        // When
        val result = chatRepository.createPersonalChat(request)

        // Then
        assertTrue(result.isSuccess)
        assertEquals("Personal Chat", result.getOrNull()?.name)
    }

    @Test
    fun `createGroupChat returns success when server returns valid response`() = runBlocking {
        // Given
        val chat = Chat(
            id = 1L,
            name = "Group Chat",
            type = ChatType.GROUP,
            providerId = 1L
        )
        val response = Response.success(chat)
        val request = CreateGroupChatRequest(
            providerId = 1L,
            participantIds = listOf(1L, 2L, 3L),
            title = "Test Group"
        )
        
        coEvery { 
            chatApiService.createGroupChat(any()) 
        } returns response

        // When
        val result = chatRepository.createGroupChat(request)

        // Then
        assertTrue(result.isSuccess)
        assertEquals("Group Chat", result.getOrNull()?.name)
    }

    @Test
    fun `createExternalChat returns success when server returns valid response`() = runBlocking {
        // Given
        val chat = Chat(
            id = 1L,
            name = "External Chat",
            type = ChatType.EXTERNAL,
            providerId = 1L
        )
        val response = Response.success(chat)
        val request = CreateExternalChatRequest(title = "External Chat")
        
        coEvery { 
            chatApiService.createExternalChat(any()) 
        } returns response

        // When
        val result = chatRepository.createExternalChat(request)

        // Then
        assertTrue(result.isSuccess)
        assertEquals("External Chat", result.getOrNull()?.name)
    }

    @Test
    fun `sendMessage returns success when server returns valid response`() = runBlocking {
        // Given
        val message = ChatMessage(
            id = 1L,
            chatId = 1L,
            content = "Hello",
            senderId = 1L,
            senderName = "User",
            timestamp = "2023-01-01T00:00:00Z",
            status = ChatMessageStatus.SENT
        )
        val response = Response.success(message)
        val request = SendMessageRequest(content = "Hello")
        
        coEvery { 
            chatApiService.sendMessage(any(), any()) 
        } returns response

        // When
        val result = chatRepository.sendMessage(1L, request)

        // Then
        assertTrue(result.isSuccess)
        assertEquals("Hello", result.getOrNull()?.content)
    }

    @Test
    fun `deleteChat returns success when server returns success`() = runBlocking {
        // Given
        val response = Response.success(Unit)
        
        coEvery { 
            chatApiService.deleteChat(any()) 
        } returns response

        // When
        val result = chatRepository.deleteChat(1L)

        // Then
        assertTrue(result.isSuccess)
    }

    @Test
    fun `reactToMessage returns success when server returns valid response`() = runBlocking {
        // Given
        val message = ChatMessage(
            id = 1L,
            chatId = 1L,
            content = "Hello",
            senderId = 1L,
            senderName = "User",
            timestamp = "2023-01-01T00:00:00Z",
            status = ChatMessageStatus.SENT
        )
        val response = Response.success(message)
        
        coEvery { 
            chatApiService.reactToMessage(any(), any(), any()) 
        } returns response

        // When
        val result = chatRepository.reactToMessage(1L, 1L, "👍")

        // Then
        assertTrue(result.isSuccess)
        assertEquals("Hello", result.getOrNull()?.content)
    }

    @Test
    fun `getUnseenCount returns success when server returns valid response`() = runBlocking {
        // Given
        val count = 5
        val response = Response.success(count)
        
        coEvery { 
            chatApiService.getUnseenCount() 
        } returns response

        // When
        val result = chatRepository.getUnseenCount()

        // Then
        assertTrue(result.isSuccess)
        assertEquals(5, result.getOrNull())
    }
}
