package com.saas.voip.service.provider.retell;

import com.saas.shared.exception.BusinessException;
import com.saas.shared.exception.ErrorCode;
import com.saas.voip.dto.request.CreateRetellAgentRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Unit Tests for RetellApiClient
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("RetellApiClient Unit Tests")
class RetellApiClientTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private RetellApiClient retellApiClient;

    private CreateRetellAgentRequest testRequest;

    @BeforeEach
    void setUp() {
        CreateRetellAgentRequest.VoiceConfig voiceConfig = CreateRetellAgentRequest.VoiceConfig.builder()
            .provider("11labs")
            .voiceId("voice_123")
            .speed(1.0)
            .build();

        testRequest = CreateRetellAgentRequest.builder()
            .agentName("Medical Agent")
            .description("AI agent for patient calls")
            .llmModel("gpt-4")
            .systemPrompt("You are a helpful medical assistant")
            .beginMessage("Hello, how can I help you?")
            .voice(voiceConfig)
            .languageCode("en-US")
            .enableTranscription(true)
            .enableRecording(true)
            .maxDurationMinutes(30)
            .build();

        // Set API key via reflection
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", "test-api-key");
        ReflectionTestUtils.setField(retellApiClient, "retellBaseUrl", "https://api.retellai.com");
    }

    @Test
    @DisplayName("Should throw exception when Retell API key not configured")
    void testCreateAgentNoApiKey() {
        // Arrange
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", "");

        // Act & Assert
        BusinessException exception = assertThrows(BusinessException.class,
            () -> retellApiClient.createAgent(testRequest));
        
        assertEquals(ErrorCode.INVALID_INPUT, exception.getErrorCode());
        assertTrue(exception.getMessage().contains("Retell API key is not configured"));
    }

    @Test
    @DisplayName("Should validate API key presence for listAgents")
    void testListAgentsNoApiKey() {
        // Arrange
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", null);

        // Act & Assert
        BusinessException exception = assertThrows(BusinessException.class,
            () -> retellApiClient.listAgents());
        
        assertEquals(ErrorCode.INVALID_INPUT, exception.getErrorCode());
    }

    @Test
    @DisplayName("Should validate API key presence for getAgent")
    void testGetAgentNoApiKey() {
        // Arrange
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", "");

        // Act & Assert
        BusinessException exception = assertThrows(BusinessException.class,
            () -> retellApiClient.getAgent("agent_123"));
        
        assertEquals(ErrorCode.INVALID_INPUT, exception.getErrorCode());
    }

    @Test
    @DisplayName("Should validate API key presence for updateAgent")
    void testUpdateAgentNoApiKey() {
        // Arrange
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", "");

        // Act & Assert
        BusinessException exception = assertThrows(BusinessException.class,
            () -> retellApiClient.updateAgent("agent_123", testRequest));
        
        assertEquals(ErrorCode.INVALID_INPUT, exception.getErrorCode());
    }

    @Test
    @DisplayName("Should validate API key presence for deleteAgent")
    void testDeleteAgentNoApiKey() {
        // Arrange
        ReflectionTestUtils.setField(retellApiClient, "retellApiKey", null);

        // Act & Assert
        BusinessException exception = assertThrows(BusinessException.class,
            () -> retellApiClient.deleteAgent("agent_123"));
        
        assertEquals(ErrorCode.INVALID_INPUT, exception.getErrorCode());
    }

    @Test
    @DisplayName("Should have correct base URL configuration")
    void testBaseUrlConfiguration() {
        String baseUrl = (String) ReflectionTestUtils.getField(retellApiClient, "retellBaseUrl");
        assertEquals("https://api.retellai.com", baseUrl);
    }

    @Test
    @DisplayName("Should validate voice config structure")
    void testVoiceConfigValidation() {
        CreateRetellAgentRequest.VoiceConfig voiceConfig = testRequest.getVoice();
        
        assertNotNull(voiceConfig);
        assertEquals("11labs", voiceConfig.getProvider());
        assertEquals("voice_123", voiceConfig.getVoiceId());
        assertEquals(1.0, voiceConfig.getSpeed());
    }
}
