package com.ycwl.basic.puzzle.fill.datasource;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
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 static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.*;

/**
 * 人脸URL数据源策略测试
 */
@DisplayName("人脸URL数据源策略测试")
@ExtendWith(MockitoExtension.class)
class FaceUrlDataSourceStrategyTest {

    @Mock
    private FaceMapper faceMapper;

    @InjectMocks
    private FaceUrlDataSourceStrategy strategy;

    private ObjectMapper objectMapper;

    @BeforeEach
    void setUp() {
        objectMapper = new ObjectMapper();
    }

    @Test
    @DisplayName("应该返回正确的支持类型")
    void shouldReturnCorrectSupportedType() {
        assertEquals("FACE_URL", strategy.getSupportedType());
    }

    @Test
    @DisplayName("当face存在且有faceUrl时应该返回URL")
    void shouldReturnFaceUrlWhenFaceExists() {
        // Given
        Long faceId = 123L;
        String expectedUrl = "https://oss.example.com/face/123.jpg";

        FaceEntity face = new FaceEntity();
        face.setId(faceId);
        face.setFaceUrl(expectedUrl);

        when(faceMapper.get(faceId)).thenReturn(face);

        DataSourceContext context = DataSourceContext.builder()
                .faceId(faceId)
                .build();

        // When
        String result = strategy.resolve(null, null, context);

        // Then
        assertEquals(expectedUrl, result);
        verify(faceMapper, times(1)).get(faceId);
    }

    @Test
    @DisplayName("当face不存在时应该返回null")
    void shouldReturnNullWhenFaceNotFound() {
        // Given
        Long faceId = 999L;

        when(faceMapper.get(faceId)).thenReturn(null);

        DataSourceContext context = DataSourceContext.builder()
                .faceId(faceId)
                .build();

        // When
        String result = strategy.resolve(null, null, context);

        // Then
        assertNull(result);
        verify(faceMapper, times(1)).get(faceId);
    }

    @Test
    @DisplayName("当face存在但faceUrl为null时应该返回null")
    void shouldReturnNullWhenFaceUrlIsNull() {
        // Given
        Long faceId = 123L;

        FaceEntity face = new FaceEntity();
        face.setId(faceId);
        face.setFaceUrl(null);

        when(faceMapper.get(faceId)).thenReturn(face);

        DataSourceContext context = DataSourceContext.builder()
                .faceId(faceId)
                .build();

        // When
        String result = strategy.resolve(null, null, context);

        // Then
        assertNull(result);
    }

    @Test
    @DisplayName("当faceMapper抛出异常时应该返回null")
    void shouldReturnNullWhenFaceMapperThrowsException() {
        // Given
        Long faceId = 123L;

        when(faceMapper.get(anyLong())).thenThrow(new RuntimeException("Database error"));

        DataSourceContext context = DataSourceContext.builder()
                .faceId(faceId)
                .build();

        // When
        String result = strategy.resolve(null, null, context);

        // Then
        assertNull(result);
    }

    @Test
    @DisplayName("sourceFilter和sortStrategy参数应该被忽略")
    void shouldIgnoreSourceFilterAndSortStrategy() throws Exception {
        // Given
        Long faceId = 123L;
        String expectedUrl = "https://oss.example.com/face/123.jpg";

        FaceEntity face = new FaceEntity();
        face.setId(faceId);
        face.setFaceUrl(expectedUrl);

        when(faceMapper.get(faceId)).thenReturn(face);

        DataSourceContext context = DataSourceContext.builder()
                .faceId(faceId)
                .build();

        JsonNode sourceFilter = objectMapper.readTree("{\"type\": 2}");
        String sortStrategy = "LATEST";

        // When
        String result = strategy.resolve(sourceFilter, sortStrategy, context);

        // Then
        assertEquals(expectedUrl, result);
    }
}
