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

import com.ycwl.basic.image.pipeline.enums.ImageSource;
import com.ycwl.basic.image.pipeline.enums.ImageType;
import com.ycwl.basic.image.pipeline.enums.PipelineScene;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

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

/**
 * PhotoProcessContext 单元测试
 */
class PhotoProcessContextTest {

    @Test
    void testBuilder_WithRequiredFields() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertNotNull(context);
        assertEquals("https://example.com/test.jpg", context.getOriginalUrl());
        assertEquals(123L, context.getScenicId());
        assertNotNull(context.getProcessId());
        assertEquals(ImageType.NORMAL_PHOTO, context.getImageType());
    }

    @Test
    void testBuilder_WithAllFields() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-123")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(456L)
                .imageType(ImageType.PUZZLE)
                .source(ImageSource.IPC)
                .scene(PipelineScene.IMAGE_PRINT)
                .build();

        assertEquals("test-123", context.getProcessId());
        assertEquals("https://example.com/test.jpg", context.getOriginalUrl());
        assertEquals(456L, context.getScenicId());
        assertEquals(ImageType.PUZZLE, context.getImageType());
        assertEquals(ImageSource.IPC, context.getSource());
        assertEquals(PipelineScene.IMAGE_PRINT, context.getScene());
    }

    @Test
    void testBuilder_MissingOriginalUrl_ShouldThrow() {
        PhotoProcessContext.Builder builder = PhotoProcessContext.builder()
                .scenicId(123L);

        Exception exception = assertThrows(IllegalArgumentException.class, builder::build);

        assertEquals("originalUrl is required", exception.getMessage());
    }

    @Test
    void testBuilder_MissingScenicId_ShouldThrow() {
        PhotoProcessContext.Builder builder = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg");

        Exception exception = assertThrows(IllegalArgumentException.class, builder::build);

        assertEquals("scenicId is required", exception.getMessage());
    }

    @Test
    void testBuilder_AutoGenerateProcessId() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertNotNull(context.getProcessId());
        assertFalse(context.getProcessId().isEmpty());
    }

    @Test
    void testForSuperResolution() {
        PhotoProcessContext context = PhotoProcessContext.forSuperResolution(
                12345L,
                "https://example.com/photo.jpg",
                678L
        );

        assertEquals("12345", context.getProcessId());
        assertEquals("https://example.com/photo.jpg", context.getOriginalUrl());
        assertEquals(678L, context.getScenicId());
        assertEquals(ImageType.NORMAL_PHOTO, context.getImageType());
        assertEquals(ImageSource.IPC, context.getSource());
        assertEquals(PipelineScene.SOURCE_PHOTO_SUPER_RESOLUTION, context.getScene());
    }

    @Test
    void testResultUrlCallback() {
        AtomicReference<String> capturedUrl = new AtomicReference<>();

        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .resultUrlCallback(capturedUrl::set)
                .build();

        context.setResultUrl("https://cdn.example.com/result.jpg");

        assertEquals("https://cdn.example.com/result.jpg", context.getResultUrl());
        assertEquals("https://cdn.example.com/result.jpg", capturedUrl.get());
    }

    @Test
    void testResultUrlCallback_WithoutCallback() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertDoesNotThrow(() -> {
            context.setResultUrl("https://cdn.example.com/result.jpg");
        });

        assertEquals("https://cdn.example.com/result.jpg", context.getResultUrl());
    }

    @Test
    void testGetCurrentFile_NoProcessedFile() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        File originalFile = new File("original.jpg");
        context.setOriginalFile(originalFile);

        assertEquals(originalFile, context.getCurrentFile());
    }

    @Test
    void testGetCurrentFile_WithProcessedFile() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        File originalFile = new File("original.jpg");
        File processedFile = new File("processed.jpg");

        context.setOriginalFile(originalFile);
        context.setProcessedFile(processedFile);

        assertEquals(processedFile, context.getCurrentFile());
    }

    @Test
    void testLoadStageConfig() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        Map<String, Boolean> stageConfig = new HashMap<>();
        stageConfig.put("watermark", false);
        stageConfig.put("enhance", true);

        context.loadStageConfig(null, stageConfig);

        assertFalse(context.isStageEnabled("watermark", true));
        assertTrue(context.isStageEnabled("enhance", false));
    }

    @Test
    void testIsStageEnabled_WithDefault() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertTrue(context.isStageEnabled("unknown_stage", true));
        assertFalse(context.isStageEnabled("unknown_stage", false));
    }

    @Test
    void testIsStageEnabled_WithConfig() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        Map<String, Boolean> config = new HashMap<>();
        config.put("watermark", false);
        context.loadStageConfig(null, config);

        assertFalse(context.isStageEnabled("watermark", true));
    }

    @Test
    void testTempFileManager() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("test-temp")
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertNotNull(context.getTempFileManager());
    }

    @Test
    void testDefaultImageType() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .build();

        assertEquals(ImageType.NORMAL_PHOTO, context.getImageType());
    }

    @Test
    void testSetImageType() {
        PhotoProcessContext context = PhotoProcessContext.builder()
                .originalUrl("https://example.com/test.jpg")
                .scenicId(123L)
                .imageType(ImageType.PUZZLE)
                .build();

        assertEquals(ImageType.PUZZLE, context.getImageType());
    }
}
