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 com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.model.Crop;
import com.ycwl.basic.model.PrinterOrderItem;
import com.ycwl.basic.image.pipeline.util.TempFileManager;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.pipeline.core.PipelineContext;
import lombok.Getter;
import lombok.Setter;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;

/**
 * 图片处理管线上下文
 * 在各个Stage之间传递状态和数据
 */
@Getter
@Setter
public class PhotoProcessContext implements PipelineContext {

    // ==================== 核心字段（构造时必填）====================

    /**
     * 处理过程唯一标识
     * 用于 TempFileManager 创建隔离的临时文件目录
     */
    private final String processId;

    /**
     * 原图 URL
     */
    private final String originalUrl;

    /**
     * 景区 ID
     */
    private final Long scenicId;

    /**
     * 临时文件管理器
     */
    private final TempFileManager tempFileManager;

    // ==================== 图片元信息 ====================

    /**
     * 图片类型
     */
    private ImageType imageType = ImageType.NORMAL_PHOTO;

    /**
     * 裁剪/旋转信息
     */
    private Crop crop;

    // ==================== 管线配置 ====================

    /**
     * 景区配置管理器,用于获取景区相关配置
     */
    private ScenicConfigManager scenicConfigManager;

    /**
     * 管线处理场景(打印、增强等)
     */
    private PipelineScene scene;

    /**
     * 图片来源(IPC、相机、手机等)
     */
    private ImageSource source;

    /**
     * Stage开关配置表
     * Key: stageId, Value: 是否启用
     * 整合了景区配置和请求参数
     */
    private Map<String, Boolean> stageEnabledMap = new HashMap<>();

    // ==================== 处理过程状态 ====================

    private File originalFile;
    private File processedFile;
    private boolean isLandscape = true;
    private boolean rotationApplied = false;
    private boolean cleaned = false;

    /**
     * 图像需要旋转的角度（用于后续Stage使用）
     * 由 ImageOrientationStage 从 Crop.rotation 中提取并设置
     */
    private Integer imageRotation;

    private String resultUrl;
    private IStorageAdapter storageAdapter;

    // ==================== 回调 ====================

    /**
     * 结果 URL 回调
     * 用于在 setResultUrl 时通知外部更新相关数据
     */
    private Consumer<String> resultUrlCallback;

    // ==================== 构造函数（私有）====================

    private PhotoProcessContext(Builder builder) {
        this.processId = builder.processId;
        this.originalUrl = builder.originalUrl;
        this.scenicId = builder.scenicId;
        this.tempFileManager = new TempFileManager(processId);

        this.imageType = builder.imageType;
        this.crop = builder.crop;
        this.scene = builder.scene;
        this.source = builder.source;
        this.resultUrlCallback = builder.resultUrlCallback;
    }

    // ==================== 静态工厂方法 ====================

    /**
     * 从 PrinterOrderItem 创建 Context（打印场景兼容方法）
     *
     * @param orderItem 打印订单项
     * @param scenicId  景区ID
     * @return PhotoProcessContext
     */
    public static PhotoProcessContext fromPrinterOrderItem(PrinterOrderItem orderItem, Long scenicId) {
        return PhotoProcessContext.builder()
                .processId(orderItem.getId().toString())
                .originalUrl(orderItem.getCropUrl())
                .scenicId(scenicId)
                .imageType(ImageType.fromSourceId(orderItem.getSourceId()))
                .crop(orderItem.getCrop())
                .resultUrlCallback(url -> orderItem.setCropUrl(url))
                .build();
    }

    /**
     * 为超分辨率场景创建 Context
     *
     * @param itemId   项目ID（用于临时文件隔离）
     * @param url      原图URL
     * @param scenicId 景区ID
     * @return PhotoProcessContext
     */
    public static PhotoProcessContext forSuperResolution(Long itemId, String url, Long scenicId) {
        return PhotoProcessContext.builder()
                .processId(itemId.toString())
                .originalUrl(url)
                .scenicId(scenicId)
                .imageType(ImageType.NORMAL_PHOTO)
                .source(ImageSource.IPC)
                .scene(PipelineScene.SOURCE_PHOTO_SUPER_RESOLUTION)
                .build();
    }

    /**
     * 获取 Builder
     */
    public static Builder builder() {
        return new Builder();
    }

    // ==================== 业务方法 ====================

    /**
     * 从景区配置和请求参数中加载Stage开关配置
     *
     * @param scenicConfigManager 景区配置管理器
     * @param requestParams       请求参数中的Stage配置
     */
    public void loadStageConfig(ScenicConfigManager scenicConfigManager, Map<String, Boolean> requestParams) {
        // 请求参数覆盖
        if (requestParams != null) {
            stageEnabledMap.putAll(requestParams);
        }
    }

    /**
     * 判断指定Stage是否启用
     *
     * @param stageId        Stage唯一标识
     * @param defaultEnabled 默认值(当配置未指定时使用)
     * @return true-启用, false-禁用
     */
    @Override
    public boolean isStageEnabled(String stageId, boolean defaultEnabled) {
        return stageEnabledMap.getOrDefault(stageId, defaultEnabled);
    }

    /**
     * 判断指定Stage是否启用(默认为false)
     *
     * @param stageId Stage唯一标识
     * @return true-启用, false-禁用
     */
    @Override
    public boolean isStageEnabled(String stageId) {
        return stageEnabledMap.getOrDefault(stageId, false);
    }

    /**
     * 设置指定Stage的启用状态
     *
     * @param stageId Stage唯一标识
     * @param enabled 是否启用
     * @return this(支持链式调用)
     */
    public PhotoProcessContext setStageState(String stageId, boolean enabled) {
        stageEnabledMap.put(stageId, enabled);
        return this;
    }

    /**
     * 启用指定Stage
     *
     * @param stageId Stage唯一标识
     * @return this(支持链式调用)
     */
    public PhotoProcessContext enableStage(String stageId) {
        stageEnabledMap.put(stageId, true);
        return this;
    }

    /**
     * 禁用指定Stage
     *
     * @param stageId Stage唯一标识
     * @return this(支持链式调用)
     */
    public PhotoProcessContext disableStage(String stageId) {
        stageEnabledMap.put(stageId, false);
        return this;
    }

    /**
     * 批量设置Stage启用状态
     *
     * @param stages Stage配置Map(stageId -> enabled)
     * @return this(支持链式调用)
     */
    public PhotoProcessContext setStages(Map<String, Boolean> stages) {
        if (stages != null) {
            stageEnabledMap.putAll(stages);
        }
        return this;
    }

    /**
     * 清空所有Stage配置
     *
     * @return this(支持链式调用)
     */
    public PhotoProcessContext clearStages() {
        stageEnabledMap.clear();
        return this;
    }

    /**
     * 设置最终处理结果URL
     */
    public void setResultUrl(String url) {
        this.resultUrl = url;
        if (resultUrlCallback != null) {
            resultUrlCallback.accept(url);
        }
    }

    /**
     * 获取当前处理中的文件
     * 如果有processedFile则返回,否则返回originalFile
     */
    public File getCurrentFile() {
        return processedFile != null ? processedFile : originalFile;
    }

    /**
     * 更新处理后的文件
     */
    public void updateProcessedFile(File newFile) {
        this.processedFile = newFile;
        tempFileManager.registerTempFile(newFile);
    }

    /**
     * 清理所有临时文件
     */
    @Override
    public void cleanup() {
        if (cleaned) {
            return;
        }
        tempFileManager.cleanup();
        cleaned = true;
    }

    // ==================== Builder ====================

    public static class Builder {
        private String processId;
        private String originalUrl;
        private Long scenicId;
        private ImageType imageType = ImageType.NORMAL_PHOTO;
        private Crop crop;
        private PipelineScene scene;
        private ImageSource source;
        private Consumer<String> resultUrlCallback;

        public Builder processId(String processId) {
            this.processId = processId;
            return this;
        }

        public Builder originalUrl(String originalUrl) {
            this.originalUrl = originalUrl;
            return this;
        }

        public Builder scenicId(Long scenicId) {
            this.scenicId = scenicId;
            return this;
        }

        public Builder imageType(ImageType imageType) {
            this.imageType = imageType;
            return this;
        }

        public Builder crop(Crop crop) {
            this.crop = crop;
            return this;
        }

        public Builder scene(PipelineScene scene) {
            this.scene = scene;
            return this;
        }

        public Builder source(ImageSource source) {
            this.source = source;
            return this;
        }

        public Builder resultUrlCallback(Consumer<String> callback) {
            this.resultUrlCallback = callback;
            return this;
        }

        public PhotoProcessContext build() {
            // 参数校验
            if (originalUrl == null || originalUrl.isBlank()) {
                throw new IllegalArgumentException("originalUrl is required");
            }
            if (scenicId == null) {
                throw new IllegalArgumentException("scenicId is required");
            }
            // processId 可以自动生成
            if (processId == null || processId.isBlank()) {
                processId = UUID.randomUUID().toString();
            }
            return new PhotoProcessContext(this);
        }
    }
}
