import {
  findObjectById,
  generateId,
  optimizeCanvasRendering,
} from "../utils/helper.js";
import { imageModeHandler } from "../utils/imageHelper.js";
import { LayerType, OperationType } from "../utils/layerHelper.js";
import { Command, CompositeCommand } from "./Command.js";
import { fabric } from "fabric-with-all";

/**
 * 批量初始化红绿图模式命令
 * 将衣服底图添加到背景层、红绿图添加到固定图层、调整位置和大小，以及设置画布背景为白色等操作合并到一个命令中
 * 减少页面闪烁，一次性渲染完成
 */
export class BatchInitializeRedGreenModeCommand extends Command {
  constructor(options = {}) {
    super({
      name: "批量初始化红绿图模式",
      description: "一次性完成红绿图模式的所有初始化操作",
    });

    this.canvas = options.canvas;
    this.layerManager = options.layerManager;
    this.toolManager = options.toolManager;
    this.clothingImageUrl = options.clothingImageUrl;
    this.redGreenImageUrl = options.redGreenImageUrl;
    this.onImageGenerated = options.onImageGenerated;
    this.normalLayerOpacity = options.normalLayerOpacity || 0.4;
    this.clothingImageOpts = options.clothingImageOpts || null; // 衣服底图选项 - 用于设置图片加载时的选项

    // 存储原始状态以便撤销
    this.originalCanvasBackground = null;
    this.originalBackgroundObject = null;
    this.originalFixedObjects = null;
    this.originalNormalObjects = null;
    this.originalNormalOpacities = new Map();
    this.originalToolState = null;
    this.originalActiveLayerId = null;

    // 存储加载的图片对象
    this.clothingImage = null;
    this.redGreenImage = null;
    this.redGreenImageMask = null;

    // 存储新创建的图层ID
    this.newEmptyLayerId = null;
  }

  async execute() {
    try {
      await optimizeCanvasRendering(this.canvas, async () => {
        // 1. 设置画布背景为白色
        this.originalCanvasBackground = this.canvas.backgroundColor;
        this.canvas.setBackgroundColor("#ffffff", () => {});

        // 2. 查找图层结构
        const layers = this.layerManager.layers?.value || [];
        const backgroundLayer = layers.find((layer) => layer.isBackground);
        const fixedLayer = layers.find((layer) => layer.isFixed);
        const normalLayers = layers.filter(
          (layer) => !layer.isBackground && !layer.isFixed
        );

        if (!backgroundLayer || !fixedLayer || normalLayers.length === 0) {
          throw new Error("缺少必要的图层结构");
        }

        const normalLayer = normalLayers[0]; // 使用第一个普通图层

        // 3. 保存原始状态
        this.originalBackgroundObject = backgroundLayer.fabricObject
          ? {
              ...backgroundLayer.fabricObject,
              ref: backgroundLayer.fabricObject,
            }
          : null;

        this.originalFixedObjects = fixedLayer.fabricObject
          ? [fixedLayer.fabricObject]
          : [];

        this.originalNormalObjects = normalLayer.fabricObjects
          ? [...normalLayer.fabricObjects]
          : [];

        // 保存当前活动图层ID
        this.originalActiveLayerId = this.layerManager.getActiveLayerId();

        // 保存普通图层透明度
        normalLayers.forEach((layer) => {
          this.originalNormalOpacities.set(layer.id, layer.opacity || 1);
          if (layer.fabricObjects) {
            layer.fabricObjects.forEach((obj) => {
              this.originalNormalOpacities.set(
                `${layer.id}_${obj.id || "unknown"}`,
                obj.opacity || 1
              );
            });
          }
        });

        // 保存工具状态
        if (this.toolManager) {
          this.originalToolState = {
            currentTool: this.toolManager.getCurrentTool(),
            isRedGreenMode: this.toolManager.isRedGreenMode,
          };
        }

        // 5. 并行加载两个图片
        const [clothingImg, redGreenImg] = await Promise.all([
          this._loadImage(this.clothingImageUrl),
          this._loadImage(this.redGreenImageUrl),
        ]);

        // 6. 设置衣服底图到固定图层
        await this._setupClothingImage(clothingImg, fixedLayer);

        // 7. 设置红绿图到普通图层，位置和大小与衣服底图一致
        await this._setupRedGreenImage(
          redGreenImg,
          normalLayer,
          this.clothingImage
        );

        // 4. 确保背景图层大小和衣服地图大小一致
        const backgroundObject = await this._setupBackgroundLayer(
          backgroundLayer,
          this.clothingImage
        );

        // 8. 设置普通图层透明度
        this._setupNormalLayerOpacity(normalLayers); // 这里不需要在这里设置透明度 由图层统一处理

        // 9. 创建新的空白图层并设置为活动图层
        // this.newEmptyLayerId = await this._createAndActivateEmptyLayer();
        this.newEmptyLayerId = normalLayers[0]?.id || null;

        // 设置普通图层的裁剪对象为衣服底图
        if (backgroundObject) {
          // const clipPathImg = this.redGreenImage;
          // clipPathImg.set({
          //   absolutePositioned: true,
          // });

          // 克隆衣服底图作为裁剪对象
          this.redGreenImageMask = await new Promise((resolve, reject) => {
            backgroundObject.clone((clonedImg) => {
              if (!clonedImg) {
                reject(new Error("无法克隆红绿图"));
                return;
              }
              resolve(clonedImg);
            });
          });

          this.redGreenImageMask.set({
            absolutePositioned: true,
            opacity: 0.01, // 设置为几乎透明
            id: generateId("redGreenImageMask_"),
          });
          // this.canvas.add(this.redGreenImageMask);
          this.canvas.clipPath = this.redGreenImageMask;
          this.redGreenImageMask.sendToBack();
          this.redGreenImageMask.setCoords();

          const activeLayer = this.layerManager.getActiveLayer();
          // activeLayer.clippingMask = this.redGreenImageMask.toObject(["id"]);
          activeLayer.opacity = this.normalLayerOpacity;
          // activeLayer?.fabricObjects.forEach((obj) => {
          //   obj.set({
          //     clipPath: clipPathImg,
          //   });
          // });
        }

        // 10. 配置工具管理器
        this._setupToolManager();

        console.log("批量红绿图模式初始化完成", {
          衣服底图: this.clothingImageUrl,
          红绿图: this.redGreenImageUrl,
          普通图层透明度: `${Math.round(this.normalLayerOpacity * 100)}%`,
          画布背景: "白色",
          新建空图层ID: this.newEmptyLayerId,
        });

        await this.layerManager.updateLayersObjectsInteractivity(false);
      });

      return true;
    } catch (error) {
      // 恢复渲染
      this.canvas.renderOnAddRemove = true;
      console.error("批量红绿图模式初始化失败:", error);
      throw error;
    }
  }

  /**
   * 创建新的空白图层并设置为活动图层
   * @returns {Promise<string>} 新创建的图层ID
   * @private
   */
  async _createAndActivateEmptyLayer() {
    // 创建新的空白图层
    const newLayerName = "绘制图层";
    const newLayerId = await this.layerManager.createLayer(
      newLayerName,
      LayerType.BITMAP,
      {
        undoable: false,
      }
    );

    // 设置为活动图层
    if (newLayerId) {
      this.layerManager.setActiveLayer(newLayerId);
    }

    return newLayerId;
  }

  async undo() {
    try {
      await optimizeCanvasRendering(this.canvas, async () => {
        // 1. 恢复画布背景
        if (this.originalCanvasBackground !== null) {
          this.canvas.setBackgroundColor(
            this.originalCanvasBackground,
            () => {}
          );
        }

        // 2. 恢复图层对象
        const layers = this.layerManager.layers?.value || [];
        const backgroundLayer = layers.find((layer) => layer.isBackground);
        const fixedLayer = layers.find((layer) => layer.isFixed);
        const normalLayers = layers.filter(
          (layer) => !layer.isBackground && !layer.isFixed
        );

        // 移除当前添加的对象
        if (this.clothingImage) {
          this.canvas.remove(this.clothingImage);
        }
        if (this.redGreenImage) {
          this.canvas.remove(this.redGreenImage);
        }

        // 移除新创建的空白图层
        if (this.newEmptyLayerId) {
          const emptyLayerIndex = layers.findIndex(
            (layer) => layer.id === this.newEmptyLayerId
          );
          if (emptyLayerIndex !== -1) {
            layers.splice(emptyLayerIndex, 1);
          }
        }

        // 恢复背景图层
        if (backgroundLayer && this.originalBackgroundObject) {
          if (this.originalBackgroundObject.ref) {
            backgroundLayer.fabricObject = this.originalBackgroundObject.ref;
          }
        }

        // 恢复固定图层
        if (fixedLayer) {
          fixedLayer.fabricObject =
            this.originalFixedObjects.length > 0
              ? this.originalFixedObjects[0]
              : null;

          if (fixedLayer.fabricObject) {
            this.canvas.add(fixedLayer.fabricObject);
          }
        }

        // 恢复普通图层
        if (normalLayers.length > 0) {
          const normalLayer = normalLayers[0];
          normalLayer.fabricObjects = [...this.originalNormalObjects];
          this.originalNormalObjects.forEach((obj) => {
            this.canvas.add(obj);
          });
        }

        // 3. 恢复透明度
        normalLayers.forEach((layer) => {
          if (this.originalNormalOpacities.has(layer.id)) {
            layer.opacity = this.originalNormalOpacities.get(layer.id);
          }

          if (layer.fabricObjects) {
            layer.fabricObjects.forEach((obj) => {
              const key = `${layer.id}_${obj.id || "unknown"}`;
              if (this.originalNormalOpacities.has(key)) {
                obj.opacity = this.originalNormalOpacities.get(key);
              }
            });
          }
        });

        // 恢复活动图层
        if (this.originalActiveLayerId) {
          this.layerManager.setActiveLayer(this.originalActiveLayerId);
        }

        // 4. 恢复工具状态
        if (this.toolManager && this.originalToolState) {
          this.toolManager.isRedGreenMode =
            this.originalToolState.isRedGreenMode;
          if (this.originalToolState.currentTool) {
            this.toolManager.setTool(this.originalToolState.currentTool);
          }
        }
      });

      return true;
    } catch (error) {
      this.canvas.renderOnAddRemove = true;
      console.error("撤销批量红绿图模式初始化失败:", error);
      return false;
    }
  }

  /**
   * 设置背景图层
   */
  async _setupBackgroundLayer(backgroundLayer, clothingImage) {
    let backgroundObject = backgroundLayer.fabricObject;
    let { object } = findObjectById(this.canvas, backgroundObject.id);

    if (!object) {
      // 创建白色背景矩形
      object = new fabric.Rect({
        left: this.canvas.width / 2,
        top: this.canvas.height / 2,
        width: clothingImage.width,
        height: clothingImage.height,
        scaleX: clothingImage.scaleX,
        scaleY: clothingImage.scaleY,
        fill: "transparent", // 确保背景是透明的
        selectable: false,
        evented: false,
        isBackground: true,
        layerId: backgroundLayer.id,
        layerName: backgroundLayer.name,
        originX: "center",
        originY: "center",
      });

      this.canvas.add(object);
      this.canvas.sendToBack(object);
      backgroundLayer.fabricObject = object.toObject(["id", "layerId", "type"]);
    } else {
      // 更新现有背景对象大小
      object.set({
        width: clothingImage.width,
        height: clothingImage.height,
        scaleX: clothingImage.scaleX,
        scaleY: clothingImage.scaleY,
        left: this.canvas.width / 2,
        top: this.canvas.height / 2,
        fill: "transparent", // 确保背景是透明的
      });
    }

    object.setCoords();

    return object;
  }

  /**
   * 加载图片
   */
  async _loadImage(imageUrl) {
    return new Promise((resolve, reject) => {
      fabric.Image.fromURL(
        imageUrl,
        (img) => {
          if (!img) {
            reject(new Error(`无法加载图片: ${imageUrl}`));
            return;
          }
          resolve(img);
        },
        { crossOrigin: "anonymous" }
      );
    });
  }

  /**
   * 设置衣服底图
   */
  async _setupClothingImage(img, fixedLayer) {
    if (this.clothingImageOpts?.imageMode) {
      // 如果有衣服底图选项，应用这些选项
      // 底图加载方式   1.平铺   2.拉伸   3.拉伸平铺  4.拉伸平铺并裁剪  5.包含
      // this.clothingImageOpts?.imageMode // 默认不处理   可选     contains, stretch,tile， stretchTile, stretchTileCrop
      // 通用处理图片模式
      imageModeHandler({
        imageMode: this.clothingImageOpts?.imageMode,
        newImage: img,
        canvasWidth: this.canvas.width,
        canvasHeight: this.canvas.height,
      });
    } else {
      // 计算图片缩放，保持上下留边距
      const margin = 50;
      const maxWidth = this.canvas.width - margin * 2;
      const maxHeight = this.canvas.height - margin * 2;
      const scale = Math.min(maxWidth / img.width, maxHeight / img.height);
      img.set({
        scaleX: scale,
        scaleY: scale,
      });
    }

    img.set({
      left: this.canvas.width / 2,
      top: this.canvas.height / 2,
      originX: "center",
      originY: "center",
      selectable: false,
      evented: false,
      layerId: fixedLayer.id,
      layerName: fixedLayer.name,
      id: generateId("clothingImage"),
    });

    // 清除固定图层原有内容
    if (fixedLayer.fabricObject) {
      const { object } = findObjectById(
        this.canvas,
        fixedLayer.fabricObject.id
      );
      if (object) this.canvas.remove(object);
    }

    // 添加到画布和固定图层
    this.canvas.add(img);
    fixedLayer.fabricObject = img.toObject(["id", "type", "layerId"]);
    this.clothingImage = img;
  }

  /**
   * 设置红绿图
   */
  async _setupRedGreenImage(img, normalLayer, clothingImage) {
    if (!clothingImage) {
      throw new Error("衣服底图未加载，无法设置红绿图位置");
    }

    if (this.clothingImageOpts?.imageMode) {
      imageModeHandler({
        imageMode: this.clothingImageOpts?.imageMode,
        newImage: img,
        canvasWidth: this.canvas.width,
        canvasHeight: this.canvas.height,
      });
    } else {
      // 使用与衣服底图完全相同的属性
      img.set({
        scaleX: clothingImage.scaleX,
        scaleY: clothingImage.scaleY,
      });
    }

    img.set({
      left: clothingImage.left,
      top: clothingImage.top,
      originX: clothingImage.originX,
      originY: clothingImage.originY,
      selectable: false,
      evented: false,
      layerId: normalLayer.id,
      layerName: normalLayer.name,
      id: generateId("redGreenImage"),
    });

    // 清除普通图层原有内容
    if (normalLayer.fabricObjects) {
      normalLayer.fabricObjects.forEach((obj) => {
        const { object } = findObjectById(this.canvas, obj.id);
        if (object) {
          this.canvas.remove(object);
        }
      });
    }
    // 添加到画布和普通图层
    this.canvas.add(img);
    normalLayer.fabricObjects = [img.toObject(["id", "type", "layerId"])];
    this.redGreenImage = img;
  }

  /**
   * 设置普通图层透明度
   */
  _setupNormalLayerOpacity(normalLayers) {
    normalLayers.forEach((layer) => {
      // 设置图层透明度
      layer.opacity = this.normalLayerOpacity;
    });
  }

  /**
   * 设置工具管理器
   */
  _setupToolManager() {
    if (this.toolManager) {
      // 设置红绿图模式
      this.toolManager.isRedGreenMode = true;

      // 切换到红色笔刷工具
      this.toolManager.setTool(OperationType.RED_BRUSH);
    }
  }
}
