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

import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
import com.ycwl.basic.pipeline.core.StageResult;
import com.ycwl.basic.image.pipeline.enums.ImageType;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Path;

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

/**
 * ConditionalRotateStage 单元测试
 */
class ConditionalRotateStageTest {

    @Test
    void testGetName() {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        assertEquals("ConditionalRotateStage", stage.getName());
    }

    @Test
    void testShouldExecute_NormalPhotoAndPortrait() {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setLandscape(false); // 竖图
        context.setImageRotation(90); // 需要旋转

        assertTrue(stage.shouldExecute(context));
    }

    @Test
    void testShouldExecute_NormalPhotoButLandscape_ShouldSkip() {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setLandscape(true); // 横图

        assertFalse(stage.shouldExecute(context));
    }

    @Test
    void testShouldExecute_Puzzle_ShouldSkip() {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/puzzle.png")
                .scenicId(123L)
                .imageType(ImageType.PUZZLE)
                .build();

        context.setLandscape(false);

        assertFalse(stage.shouldExecute(context));
    }

    @Test
    void testExecute_NoCurrentFile_ShouldFail() {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setLandscape(false);

        StageResult result = stage.execute(context);

        assertTrue(result.isFailed());
        assertEquals("当前文件不存在", result.getMessage());
    }

    /**
     * 测试旋转90度
     */
    @Test
    void testExecute_Rotate90(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-rotate-90")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(90);

        StageResult result = stage.execute(context);

        assertTrue(result.isSuccess());
        assertEquals("已旋转90度", result.getMessage());
        assertTrue(context.isRotationApplied());
        assertNotNull(context.getCurrentFile());
    }

    /**
     * 测试旋转180度
     */
    @Test
    void testExecute_Rotate180(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-rotate-180")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(180);

        StageResult result = stage.execute(context);

        assertTrue(result.isSuccess());
        assertEquals("已旋转180度", result.getMessage());
        assertTrue(context.isRotationApplied());
    }

    /**
     * 测试旋转270度
     */
    @Test
    void testExecute_Rotate270(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-rotate-270")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(270);

        StageResult result = stage.execute(context);

        assertTrue(result.isSuccess());
        assertEquals("已旋转270度", result.getMessage());
        assertTrue(context.isRotationApplied());
    }

    /**
     * 测试无需旋转（rotation=0）
     */
    @Test
    void testExecute_NoRotationNeeded(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-no-rotation")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(0);

        StageResult result = stage.execute(context);

        assertTrue(result.isSkipped());
        assertEquals("无需旋转", result.getMessage());
    }

    /**
     * 测试无需旋转（rotation=null）
     */
    @Test
    void testExecute_NullRotation(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-null-rotation")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(null);

        StageResult result = stage.execute(context);

        assertTrue(result.isSkipped());
        assertEquals("无需旋转", result.getMessage());
    }

    /**
     * 测试不支持的旋转角度
     */
    @Test
    void testExecute_UnsupportedRotationAngle(@TempDir Path tempDir) throws Exception {
        ConditionalRotateStage stage = new ConditionalRotateStage();

        File testFile = createTestImage(tempDir, "test.jpg", 1080, 1920);

        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-unsupported-rotation")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.NORMAL_PHOTO)
                .build();

        context.setOriginalFile(testFile);
        context.setLandscape(false);
        context.setImageRotation(45);

        StageResult result = stage.execute(context);

        assertTrue(result.isFailed());
        assertTrue(result.getMessage().contains("不支持的旋转角度"));
    }

    /**
     * 创建测试用的图片文件
     */
    private File createTestImage(Path tempDir, String filename, int width, int height) throws Exception {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        File file = tempDir.resolve(filename).toFile();
        ImageIO.write(image, "jpg", file);
        return file;
    }
}
