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.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.service.pc.helper.FaceMetricsRecorder;
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 static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

/**
 * RecordMetricsStage 单元测试
 */
@ExtendWith(MockitoExtension.class)
class RecordMetricsStageTest {

    @Mock
    private FaceMetricsRecorder metricsRecorder;

    @InjectMocks
    private RecordMetricsStage stage;

    private FaceMatchingContext context;
    private FaceEntity face;

    @BeforeEach
    void setUp() {
        context = FaceMatchingContext.forAutoMatching(1L, true);

        face = new FaceEntity();
        face.setId(1L);
        face.setMemberId(100L);
        face.setScenicId(10L);

        context.setFace(face);
    }

    @Test
    void testExecute_NoSearchResult_Success() {
        // Given: searchResult为null
        context.setSearchResult(null);

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

        // Then
        assertTrue(result.isSuccess());
        assertTrue(result.getMessage().contains("识别指标记录完成"));
        verify(metricsRecorder, times(1)).recordRecognitionCount(1L);
        verify(metricsRecorder, never()).recordLowThreshold(anyLong());
    }

    @Test
    void testExecute_SearchResultNotLowThreshold_Success() {
        // Given: searchResult不为null,但未触发低阈值
        SearchFaceRespVo searchResult = new SearchFaceRespVo();
        searchResult.setLowThreshold(false);
        context.setSearchResult(searchResult);

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

        // Then
        assertTrue(result.isSuccess());
        verify(metricsRecorder, times(1)).recordRecognitionCount(1L);
        verify(metricsRecorder, never()).recordLowThreshold(anyLong());
    }

    @Test
    void testExecute_LowThresholdTriggered_Success() {
        // Given: searchResult触发低阈值
        SearchFaceRespVo searchResult = new SearchFaceRespVo();
        searchResult.setLowThreshold(true);
        context.setSearchResult(searchResult);

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

        // Then
        assertTrue(result.isSuccess());
        assertTrue(result.getMessage().contains("识别指标记录完成"));
        verify(metricsRecorder, times(1)).recordRecognitionCount(1L);
        verify(metricsRecorder, times(1)).recordLowThreshold(1L);
    }

    @Test
    void testExecute_RecordCountFailed_Degraded() {
        // Given: 记录识别次数失败
        doThrow(new RuntimeException("Record error"))
                .when(metricsRecorder).recordRecognitionCount(1L);

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("指标记录失败"));
        verify(metricsRecorder, times(1)).recordRecognitionCount(1L);
        verify(metricsRecorder, never()).recordLowThreshold(anyLong());
    }

    @Test
    void testExecute_RecordLowThresholdFailed_Degraded() {
        // Given: 记录低阈值失败
        SearchFaceRespVo searchResult = new SearchFaceRespVo();
        searchResult.setLowThreshold(true);
        context.setSearchResult(searchResult);

        doThrow(new RuntimeException("Low threshold record error"))
                .when(metricsRecorder).recordLowThreshold(1L);

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("指标记录失败"));
        verify(metricsRecorder, times(1)).recordRecognitionCount(1L);
        verify(metricsRecorder, times(1)).recordLowThreshold(1L);
    }

    @Test
    void testExecute_DifferentFaceId() {
        // Given: 不同的faceId
        context = FaceMatchingContext.forAutoMatching(999L, true);
        face.setId(999L);
        context.setFace(face);

        SearchFaceRespVo searchResult = new SearchFaceRespVo();
        searchResult.setLowThreshold(true);
        context.setSearchResult(searchResult);

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

        // Then
        assertTrue(result.isSuccess());
        verify(metricsRecorder, times(1)).recordRecognitionCount(999L);
        verify(metricsRecorder, times(1)).recordLowThreshold(999L);
    }

    @Test
    void testExecute_NullPointerException_Degraded() {
        // Given: 空指针异常
        doThrow(new NullPointerException("Null recorder"))
                .when(metricsRecorder).recordRecognitionCount(1L);

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("指标记录失败"));
    }
}
