package dev.rheinsw.contactService.service;

import dev.rheinsw.contactService.config.HCaptchaConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;

@ExtendWith(MockitoExtension.class)
class HCaptchaValidatorTest {

    @Mock
    private HCaptchaConfig hCaptchaConfig;

    @Mock
    private RestTemplate restTemplate;

    private HCaptchaValidator validator;

    @BeforeEach
    void setUp() {
        validator = new HCaptchaValidator(hCaptchaConfig, restTemplate);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenTokenIsNull() {
        // Arrange

        // Act
        boolean result = validator.isValid(null);

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenTokenIsBlank() {
        // Arrange

        // Act
        boolean result = validator.isValid(" ");

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenSecretIsNull() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn(null);

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenSecretIsBlank() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn(" ");

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenApiResponseIsNull() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn("test-secret");
        Mockito.when(restTemplate.postForObject(
                eq("https://api.hcaptcha.com/siteverify"),
                any(),
                eq(Map.class)
        )).thenReturn(null);

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenApiResponseSuccessIsFalse() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn("test-secret");
        Mockito.when(restTemplate.postForObject(
                eq("https://api.hcaptcha.com/siteverify"),
                any(),
                eq(Map.class)
        )).thenReturn(Map.of("success", false));

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertFalse(result);
    }

    @Test
    void isValid_ShouldReturnTrue_WhenApiResponseSuccessIsTrue() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn("test-secret");
        Mockito.when(restTemplate.postForObject(
                eq("https://api.hcaptcha.com/siteverify"),
                any(),
                eq(Map.class)
        )).thenReturn(Map.of("success", true));

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertTrue(result);
    }

    @Test
    void isValid_ShouldReturnFalse_WhenExceptionIsThrown() {
        // Arrange
        Mockito.when(hCaptchaConfig.getSecret()).thenReturn("test-secret");
        Mockito.when(restTemplate.postForObject(
                eq("https://api.hcaptcha.com/siteverify"),
                any(),
                eq(Map.class)
        )).thenThrow(new RuntimeException("Simulated Exception"));

        // Act
        boolean result = validator.isValid("test-token");

        // Assert
        assertFalse(result);
    }
}
