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.integration.common.manager.ScenicConfigManager;
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.*;

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

/**
 * FilterByTimeRangeStage 单元测试
 */
@ExtendWith(MockitoExtension.class)
class FilterByTimeRangeStageTest {

    @InjectMocks
    private FilterByTimeRangeStage stage;

    @Mock
    private ScenicConfigManager scenicConfig;

    private FaceMatchingContext context;

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

    @Test
    void testExecute_Success_FilterBySampleTime() {
        // Given: 设置tour_time为30分钟
        when(scenicConfig.getInteger("tour_time")).thenReturn(30);

        Date baseTime = new Date();
        Date time10MinBefore = new Date(baseTime.getTime() - 10 * 60 * 1000); // 10分钟前
        Date time20MinBefore = new Date(baseTime.getTime() - 20 * 60 * 1000); // 20分钟前
        Date time40MinBefore = new Date(baseTime.getTime() - 40 * 60 * 1000); // 40分钟前 (超出范围)

        FaceSampleEntity sample1 = createSample(101L, baseTime);
        FaceSampleEntity sample2 = createSample(102L, time10MinBefore);
        FaceSampleEntity sample3 = createSample(103L, time20MinBefore);
        FaceSampleEntity sample4 = createSample(104L, time40MinBefore);

        context.setFaceSamples(Arrays.asList(sample1, sample2, sample3, sample4));
        context.setSampleListIds(Arrays.asList(101L, 102L, 103L, 104L));

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

        // Then
        assertTrue(result.isSuccess());
        List<Long> filteredIds = context.getSampleListIds();
        assertEquals(3, filteredIds.size());
        assertTrue(filteredIds.contains(101L));
        assertTrue(filteredIds.contains(102L));
        assertTrue(filteredIds.contains(103L));
        assertFalse(filteredIds.contains(104L)); // 40分钟前的被过滤
    }

    @Test
    void testExecute_EmptyFaceSamples_Skip() {
        // Given
        context.setFaceSamples(Collections.emptyList());
        context.setSampleListIds(Arrays.asList(101L, 102L));

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

        // Then
        assertTrue(result.isSkipped());
    }

    @Test
    void testExecute_NullFaceSamples_Skip() {
        // Given
        context.setFaceSamples(null);
        context.setSampleListIds(Arrays.asList(101L, 102L));

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

        // Then
        assertTrue(result.isSkipped());
    }

    @Test
    void testExecute_TourTimeZero_Skip() {
        // Given
        when(scenicConfig.getInteger("tour_time")).thenReturn(0);

        FaceSampleEntity sample1 = createSample(101L, new Date());
        context.setFaceSamples(Arrays.asList(sample1));
        context.setSampleListIds(Arrays.asList(101L));

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

        // Then
        assertTrue(result.isSkipped());
    }

    @Test
    void testExecute_TourTimeNull_Skip() {
        // Given
        when(scenicConfig.getInteger("tour_time")).thenReturn(null);

        FaceSampleEntity sample1 = createSample(101L, new Date());
        context.setFaceSamples(Arrays.asList(sample1));
        context.setSampleListIds(Arrays.asList(101L));

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

        // Then
        assertTrue(result.isSkipped());
    }

    @Test
    void testExecute_NoValidCreateTime_Success() {
        // Given
        when(scenicConfig.getInteger("tour_time")).thenReturn(30);

        FaceSampleEntity sample1 = createSample(101L, null); // 无创建时间
        FaceSampleEntity sample2 = createSample(102L, null);

        context.setFaceSamples(Arrays.asList(sample1, sample2));
        context.setSampleListIds(Arrays.asList(101L, 102L));

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

        // Then
        assertTrue(result.isSuccess());
        assertTrue(result.getMessage().contains("样本无拍摄时间"));
    }

    @Test
    void testExecute_SampleNotInCache_Filtered() {
        // Given: sampleListIds中有样本ID,但faceSamples缓存中没有
        when(scenicConfig.getInteger("tour_time")).thenReturn(30);

        FaceSampleEntity sample1 = createSample(101L, new Date());
        context.setFaceSamples(Arrays.asList(sample1));
        context.setSampleListIds(Arrays.asList(101L, 102L, 103L)); // 102和103不在缓存中

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

        // Then
        assertTrue(result.isSuccess());
        List<Long> filteredIds = context.getSampleListIds();
        assertEquals(1, filteredIds.size());
        assertEquals(101L, filteredIds.get(0));
    }

    @Test
    void testExecute_AllSamplesWithinRange() {
        // Given: 所有样本都在时间范围内
        when(scenicConfig.getInteger("tour_time")).thenReturn(60);

        Date baseTime = new Date();
        Date time30MinBefore = new Date(baseTime.getTime() - 30 * 60 * 1000);

        FaceSampleEntity sample1 = createSample(101L, baseTime);
        FaceSampleEntity sample2 = createSample(102L, time30MinBefore);

        context.setFaceSamples(Arrays.asList(sample1, sample2));
        context.setSampleListIds(Arrays.asList(101L, 102L));

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

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

    @Test
    void testExecute_Exception_Degraded() {
        // Given
        when(scenicConfig.getInteger("tour_time")).thenReturn(30);

        FaceSampleEntity sample1 = createSample(101L, new Date());
        context.setFaceSamples(Arrays.asList(sample1));
        context.setSampleListIds(null); // 会导致异常

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("时间范围筛选失败"));
    }

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