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

import com.ycwl.basic.face.pipeline.core.FaceMatchingContext;
import com.ycwl.basic.pipeline.core.StageResult;
import com.ycwl.basic.face.pipeline.enums.FaceMatchingScene;
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.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;

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

/**
 * LoadMatchedSamplesStage 单元测试
 */
@ExtendWith(MockitoExtension.class)
class LoadMatchedSamplesStageTest {

    @Mock
    private FaceSampleMapper faceSampleMapper;

    @InjectMocks
    private LoadMatchedSamplesStage stage;

    private FaceMatchingContext context;

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

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

        FaceSampleEntity sample1 = createSample(101L, 1L, new Date());
        FaceSampleEntity sample2 = createSample(102L, 1L, new Date());
        FaceSampleEntity sample3 = createSample(103L, 2L, new Date());

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

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

        // Then
        assertTrue(result.isSuccess());
        assertEquals(3, context.getFaceSamples().size());
        assertEquals(101L, context.getFaceSamples().get(0).getId());
        verify(faceSampleMapper, times(1)).listByIds(sampleIds);
    }

    @Test
    void testExecute_EmptySampleListIds_Skip() {
        // Given
        context.setSampleListIds(Collections.emptyList());

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

        // Then
        assertTrue(result.isSkipped());
        verify(faceSampleMapper, never()).listByIds(anyList());
    }

    @Test
    void testExecute_NullSampleListIds_Skip() {
        // Given
        context.setSampleListIds(null);

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

        // Then
        assertTrue(result.isSkipped());
        verify(faceSampleMapper, never()).listByIds(anyList());
    }

    @Test
    void testExecute_NoSamplesFound_Skipped() {
        // Given
        List<Long> sampleIds = Arrays.asList(101L, 102L);
        context.setSampleListIds(sampleIds);

        when(faceSampleMapper.listByIds(sampleIds))
                .thenReturn(Collections.emptyList());

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

        // Then
        assertTrue(result.isSkipped());
        assertNull(context.getFaceSamples());
        verify(faceSampleMapper, times(1)).listByIds(sampleIds);
    }

    @Test
    void testExecute_MapperThrowsException_Failure() {
        // Given
        List<Long> sampleIds = Arrays.asList(101L, 102L);
        context.setSampleListIds(sampleIds);

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

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

        // Then
        assertTrue(result.isFailed());
        assertTrue(result.getMessage().contains("加载匹配样本实体失败"));
        verify(faceSampleMapper, times(1)).listByIds(sampleIds);
    }

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

        FaceSampleEntity sample1 = createSample(101L, 1L, new Date());
        FaceSampleEntity sample2 = createSample(102L, 1L, new Date());

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

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

        // Then
        assertTrue(result.isSuccess());
        assertEquals(2, context.getFaceSamples().size());
    }

    private FaceSampleEntity createSample(Long id, Long deviceId, Date createAt) {
        FaceSampleEntity sample = new FaceSampleEntity();
        sample.setId(id);
        sample.setDeviceId(deviceId);
        sample.setCreateAt(createAt);
        return sample;
    }
}
