package com.ycwl.basic.face.pipeline.stages;

import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.face.pipeline.core.FaceMatchingContext;
import com.ycwl.basic.pipeline.core.StageResult;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import org.junit.jupiter.api.BeforeEach;
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.*;

/**
 * LoadFaceSamplesStage 单元测试
 */
@ExtendWith(MockitoExtension.class)
class LoadFaceSamplesStageTest {

    @Mock
    private FaceSampleMapper faceSampleMapper;

    @InjectMocks
    private LoadFaceSamplesStage stage;

    private FaceMatchingContext context;

    @BeforeEach
    void setUp() {
        context = FaceMatchingContext.forCustomMatching(1L, Arrays.asList(101L, 102L));
    }

    @Test
    void testExecute_Success() {
        // Given
        List<Long> faceSampleIds = Arrays.asList(101L, 102L, 103L);
        context.setFaceSampleIds(faceSampleIds);

        FaceSampleEntity sample1 = createSample(101L, "http://example.com/s1.jpg");
        FaceSampleEntity sample2 = createSample(102L, "http://example.com/s2.jpg");
        FaceSampleEntity sample3 = createSample(103L, "http://example.com/s3.jpg");

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(Arrays.asList(sample1, sample2, sample3));

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isSuccess());
        assertEquals(3, context.getFaceSamples().size());
        assertTrue(result.getMessage().contains("加载了3个人脸样本"));
        verify(faceSampleMapper, times(1)).listByIds(faceSampleIds);
    }

    @Test
    void testExecute_FaceSampleIdsNull_Failed() {
        // Given
        context.setFaceSampleIds(null);

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isFailed());
        assertTrue(result.getMessage().contains("faceSampleIds不能为空"));
        verify(faceSampleMapper, never()).listByIds(anyList());
    }

    @Test
    void testExecute_FaceSampleIdsEmpty_Failed() {
        // Given
        context.setFaceSampleIds(new ArrayList<>());

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isFailed());
        assertTrue(result.getMessage().contains("faceSampleIds不能为空"));
        verify(faceSampleMapper, never()).listByIds(anyList());
    }

    @Test
    void testExecute_NoSamplesFound_ThrowException() {
        // Given
        List<Long> faceSampleIds = Arrays.asList(101L, 102L);
        context.setFaceSampleIds(faceSampleIds);

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(new ArrayList<>()); // 返回空列表

        // When & Then
        assertThrows(BaseException.class, () -> {
            stage.execute(context);
        });

        verify(faceSampleMapper, times(1)).listByIds(faceSampleIds);
    }

    @Test
    void testExecute_PartialSamplesFound() {
        // Given: 请求3个样本，只返回2个
        List<Long> faceSampleIds = Arrays.asList(101L, 102L, 103L);
        context.setFaceSampleIds(faceSampleIds);

        FaceSampleEntity sample1 = createSample(101L, "http://example.com/s1.jpg");
        FaceSampleEntity sample2 = createSample(102L, "http://example.com/s2.jpg");

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(Arrays.asList(sample1, sample2)); // 只返回2个

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isSuccess()); // 只要有样本就成功
        assertEquals(2, context.getFaceSamples().size());
        assertTrue(result.getMessage().contains("加载了2个人脸样本"));
    }

    @Test
    void testExecute_MapperThrowsException_Failed() {
        // Given
        List<Long> faceSampleIds = Arrays.asList(101L, 102L);
        context.setFaceSampleIds(faceSampleIds);

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenThrow(new RuntimeException("Database connection error"));

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isFailed());
        assertTrue(result.getMessage().contains("加载人脸样本失败"));
        assertNotNull(result.getException());
    }

    @Test
    void testExecute_BaseException_Rethrow() {
        // Given
        List<Long> faceSampleIds = Arrays.asList(101L, 102L);
        context.setFaceSampleIds(faceSampleIds);

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(new ArrayList<>()); // 触发BaseException

        // When & Then
        BaseException exception = assertThrows(BaseException.class, () -> {
            stage.execute(context);
        });

        assertTrue(exception.getMessage().contains("未找到指定的人脸样本"));
    }

    @Test
    void testExecute_SingleSample() {
        // Given: 只加载1个样本
        List<Long> faceSampleIds = Arrays.asList(101L);
        context.setFaceSampleIds(faceSampleIds);

        FaceSampleEntity sample = createSample(101L, "http://example.com/s1.jpg");

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(Arrays.asList(sample));

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isSuccess());
        assertEquals(1, context.getFaceSamples().size());
        assertTrue(result.getMessage().contains("加载了1个人脸样本"));
    }

    @Test
    void testExecute_ManySamples() {
        // Given: 加载大量样本
        List<Long> faceSampleIds = Arrays.asList(101L, 102L, 103L, 104L, 105L, 106L, 107L, 108L, 109L, 110L);
        context.setFaceSampleIds(faceSampleIds);

        List<FaceSampleEntity> samples = new ArrayList<>();
        for (Long id : faceSampleIds) {
            samples.add(createSample(id, "http://example.com/s" + id + ".jpg"));
        }

        when(faceSampleMapper.listByIds(faceSampleIds))
                .thenReturn(samples);

        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isSuccess());
        assertEquals(10, context.getFaceSamples().size());
        assertTrue(result.getMessage().contains("加载了10个人脸样本"));
    }

    private FaceSampleEntity createSample(Long id, String faceUrl) {
        FaceSampleEntity sample = new FaceSampleEntity();
        sample.setId(id);
        sample.setFaceUrl(faceUrl);
        sample.setDeviceId(1L);
        return sample;
    }
}
