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.helper.PuzzleGenerationOrchestrator;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
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.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

/**
 * GeneratePuzzleStage 单元测试
 */
@ExtendWith(MockitoExtension.class)
class GeneratePuzzleStageTest {

    @Mock
    private PuzzleGenerationOrchestrator puzzleOrchestrator;

    @InjectMocks
    private GeneratePuzzleStage 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);
        face.setFaceUrl("http://example.com/face1.jpg");

        context.setFace(face);
    }

    @Test
    void testExecute_Success() {
        // Given: 正常执行
        // When
        StageResult<FaceMatchingContext> result = stage.execute(context);

        // Then
        assertTrue(result.isSuccess());
        assertTrue(result.getMessage().contains("拼图模板已提交异步生成"));
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, "http://example.com/face1.jpg");
    }

    @Test
    void testExecute_EmptyFaceUrl_Success() {
        // Given: faceUrl为空字符串
        face.setFaceUrl("");

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, "");
    }

    @Test
    void testExecute_NullFaceUrl_Success() {
        // Given: faceUrl为null
        face.setFaceUrl(null);

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, null);
    }

    @Test
    void testExecute_OrchestratorFailed_Degraded() {
        // Given: orchestrator执行失败
        doThrow(new RuntimeException("Orchestrator error"))
                .when(puzzleOrchestrator).generateAllTemplatesAsync(
                        10L, 1L, 100L, "http://example.com/face1.jpg");

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("提交拼图生成任务失败"));
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, "http://example.com/face1.jpg");
    }

    @Test
    void testExecute_DifferentScenicId() {
        // Given: 不同的景区ID
        face.setScenicId(888L);

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(888L, 1L, 100L, "http://example.com/face1.jpg");
    }

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

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 777L, 100L, "http://example.com/face1.jpg");
    }

    @Test
    void testExecute_DifferentMemberId() {
        // Given: 不同的memberId
        face.setMemberId(999L);

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 999L, "http://example.com/face1.jpg");
    }

    @Test
    void testExecute_DifferentFaceUrl() {
        // Given: 不同的faceUrl
        face.setFaceUrl("http://cdn.example.com/face999.jpg");

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, "http://cdn.example.com/face999.jpg");
    }

    @Test
    void testExecute_LongFaceUrl() {
        // Given: 很长的faceUrl
        String longUrl = "http://cdn.example.com/very/long/path/to/face/image/with/many/segments/" +
                "face_id_1234567890_scenic_10_member_100_timestamp_1234567890.jpg";
        face.setFaceUrl(longUrl);

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, longUrl);
    }

    @Test
    void testExecute_NullPointerException_Degraded() {
        // Given: 空指针异常
        doThrow(new NullPointerException("Null orchestrator"))
                .when(puzzleOrchestrator).generateAllTemplatesAsync(
                        anyLong(), anyLong(), anyLong(), anyString());

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("提交拼图生成任务失败"));
    }

    @Test
    void testExecute_IllegalArgumentException_Degraded() {
        // Given: 非法参数异常
        doThrow(new IllegalArgumentException("Invalid face URL"))
                .when(puzzleOrchestrator).generateAllTemplatesAsync(
                        10L, 1L, 100L, "http://example.com/face1.jpg");

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

        // Then
        assertTrue(result.isDegraded());
        assertTrue(result.getMessage().contains("提交拼图生成任务失败"));
    }

    @Test
    void testExecute_OldUser() {
        // Given: 老用户
        context = FaceMatchingContext.forAutoMatching(1L, false);
        context.setFace(face);

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

        // Then
        assertTrue(result.isSuccess());
        verify(puzzleOrchestrator, times(1))
                .generateAllTemplatesAsync(10L, 1L, 100L, "http://example.com/face1.jpg");
    }
}
