import {
  createLayer,
  findInChildLayers,
  LayerType,
} from "../utils/layerHelper.js";
import { createRasterizedImage } from "../utils/selectionToImage.js";
import { CompositeCommand, Command } from "./Command.js";
import { CreateImageLayerCommand } from "./LayerCommands.js";
import { fabric } from "fabric-with-all";
import { generateId } from "../utils/helper.js";
import { ClearSelectionCommand } from "./LassoCutoutCommand.js";
import { ClearSelectionContentCommand } from "./ClearSelectionContentCommand.js";
import i18n from "@/lang/index.ts";
const { t } = i18n.global;

/**
 * 剪切选区到新图层命令
 * 实现将选区内容复制到新图层，并将复制的选区作为组的遮罩
 */
export class CutSelectionToNewLayerCommand extends CompositeCommand {
  constructor(options = {}) {
    super([], {
      name: "套索抠图",
      description: "将选区抠图到新图层",
    });
    this.canvas = options.canvas;
    this.layerManager = options.layerManager;
    this.selectionManager = options.selectionManager;
    this.toolManager = options.toolManager;
    this.sourceLayerId = options.sourceLayerId;
    this.newLayerName = options.newLayerName || "抠图";
    this.newLayerId = null;
    this.cutoutImageUrl = null;
    this.fabricImage = null;
    this.executedCommands = [];
    // 高清截图选项
    this.highResolutionEnabled = options.highResolutionEnabled !== false; // 默认启用
    this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数

    this.groupId = options.groupId || generateId("lasso-copy-group-");
    this.groupName = options.groupName || t(`Canvas.ConstituencyGroup`);
    this.groupLayer = null; // 新增：保存组图层的引用
    this.originalLayersLength = 0; // 新增：保存原始图层数量

    this.clippingMaskId = generateId("clipping-mask-");

    // 在初始化时克隆保存选区对象，避免撤销后重做时获取不到选区对象
    this._clonedSelectionObject = null;
    this._initializeClonedSelection();
  }

  /**
   * 初始化克隆的选区对象
   * @private
   */
  async _initializeClonedSelection() {
    if (this.selectionManager) {
      const selectionObject = this.selectionManager.getSelectionObject();
      if (selectionObject) {
        try {
          this._clonedSelectionObject = await this._cloneObject(
            selectionObject
          );
          console.log("套索抠图：选区对象已克隆保存");
        } catch (error) {
          console.error("套索抠图：克隆选区对象失败:", error);
          // 备用方案：序列化保存
          this.serializedSelectionObject = selectionObject.toObject([
            "id",
            "layerId",
            "layerName",
            "parentId",
          ]);
        }
      }
    }
  }

  async execute() {
    if (!this.canvas || !this.layerManager || !this.selectionManager) {
      console.error("无法执行套索抠图：参数无效");
      return false;
    }

    try {
      this.executedCommands = [];

      // 保存原始图层数量，用于撤销时的验证
      this.originalLayersLength = this.layerManager.layers.value.length;

      // 获取选区：优先使用克隆的选区对象
      const selectionObject = await this._getSelectionObject();
      if (!selectionObject) {
        console.error("无法执行套索抠图：当前没有选区");
        return false;
      }

      // 确定源图层
      const sourceLayer = this.layerManager.getActiveLayer();
      if (!sourceLayer) {
        console.error("无法执行套索抠图：源图层无效");
        return false;
      }

      // 获取源图层的所有对象（包括子图层）
      const sourceObjects = this._getLayerObjects(sourceLayer);
      if (sourceObjects.length === 0) {
        console.error("无法执行套索抠图：源图层没有可见对象");
        return false;
      }

      const clippingMask = fabric.util.object.clone(selectionObject);
      clippingMask.set({
        id: this.clippingMaskId,
        selectable: false,
        evented: false,
        hasControls: false,
        // layerId: this.groupId,
        visible: true,
      });

      // 获取选区边界信息用于后续定位
      const selectionBounds = selectionObject.getBoundingRect(true, true);

      // 使用createRasterizedImage执行抠图操作
      // this.cutoutImageUrl = await this._performCutoutWithRasterized(
      //   sourceObjects,
      //   selectionObject,
      //   selectionBounds
      // );
      // if (!this.cutoutImageUrl) {
      //   console.error("抠图失败");
      //   return false;
      // }

      this.fabricImage = await this._performCutoutWithRasterized(
        sourceObjects,
        selectionObject,
        selectionBounds
      );

      // // 创建fabric图像对象，传递选区边界信息
      // this.fabricImage = await this._createFabricImage(
      //   this.cutoutImageUrl,
      //   selectionBounds
      // );
      if (!this.fabricImage) {
        console.error("创建图像对象失败");
        return false;
      }

      // 1. 创建图像图层命令
      const createImageLayerCmd = new CreateImageLayerCommand({
        layerManager: this.layerManager,
        fabricImage: this.fabricImage,
        toolManager: this.toolManager,
        layerName: this.newLayerName,
      });

      // 执行创建图像图层命令
      const result = await createImageLayerCmd.execute();
      this.newLayerId = createImageLayerCmd.newLayerId;
      this.executedCommands.push(createImageLayerCmd);

      // 2. 清除选区命令
      const clearSelectionCmd = new ClearSelectionCommand({
        canvas: this.canvas,
        selectionManager: this.selectionManager,
      });

      // 执行清除选区命令
      await clearSelectionCmd.execute();
      this.executedCommands.push(clearSelectionCmd);

      const topLayerIndex = this.layerManager.layers.value.findIndex(
        (layer) => layer.id === this.newLayerId
      );

      const selectLayer = this.layerManager.layers.value[topLayerIndex];

      // 创建新的组图层
      this.groupLayer = createLayer({
        id: this.groupId,
        name: this.groupName || t(`Canvas.ConstituencyGroup`),
        type: LayerType.GROUP,
        visible: true,
        locked: false,
        opacity: 1.0,
        fabricObjects: [],
        children: [],
      });

      this.fabricImage.set({
        selectable: true,
        evented: true,
      });

      selectLayer.parentId = this.groupId; // 设置新图层的parentId为组图层ID
      selectLayer.fabricObjects = [
        this.fabricImage.toObject("id", "layerId", "layerName", "parentId"),
      ];

      this.groupLayer.clippingMask = clippingMask.toObject(["id", "layerId"]); // 设置组图层的fabricObject为遮罩图像

      this.groupLayer.children.push(selectLayer);

      selectionObject.set({
        id: generateId("selectionObject-"),
        customType: "selectionObject",
      });

      this.groupLayer.selectObject = selectionObject.toObject([
        "id",
        "customType",
      ]);

      // 插入新组图层
      this.layerManager.layers.value.splice(topLayerIndex, 1, this.groupLayer);

      this.canvas.discardActiveObject();
      this.canvas.setActiveObject(this.fabricImage);
      await this.layerManager.updateLayersObjectsInteractivity(true);

      console.log(`套索抠图完成，新图层ID: ${this.newLayerId}`);
      return {
        newLayerId: this.newLayerId,
        cutoutImageUrl: this.cutoutImageUrl,
        guroupId: this.groupId,
        groupName: this.groupName,
      };
    } catch (error) {
      console.error("套索抠图过程中出错:", error);

      // 如果已经创建了新图层，需要进行清理
      if (this.newLayerId) {
        try {
          await this.layerManager.removeLayer(this.newLayerId);
        } catch (cleanupError) {
          console.warn("清理新图层失败:", cleanupError);
        }
      }

      // 清理组图层（如果已创建）
      if (this.groupLayer && this.groupId) {
        try {
          const groupIndex = this.layerManager.layers.value.findIndex(
            (layer) => layer.id === this.groupId
          );
          if (groupIndex !== -1) {
            this.layerManager.layers.value.splice(groupIndex, 1);
            console.log(`清理了异常创建的组图层: ${this.groupId}`);
          }
          this.groupLayer = null;
        } catch (cleanupError) {
          console.warn("清理组图层失败:", cleanupError);
        }
      }

      // 尝试回滚已执行的命令
      if (this.executedCommands.length > 0) {
        try {
          for (let i = this.executedCommands.length - 1; i >= 0; i--) {
            const command = this.executedCommands[i];
            if (command && typeof command.undo === "function") {
              await command.undo();
            }
          }
          this.executedCommands = [];
        } catch (rollbackError) {
          console.warn("回滚已执行命令失败:", rollbackError);
        }
      }

      throw error;
    }
  }

  async undo() {
    try {
      console.log(`↩️ 开始撤销套索抠图操作`);

      // 1. 首先移除组图层（如果存在）
      if (this.groupId) {
        const groupIndex = this.layerManager.layers.value.findIndex(
          (layer) => layer.id === this.groupId
        );

        if (groupIndex !== -1) {
          console.log(`↩️ 移除组图层: ${this.groupId}`);
          // 从图层列表中移除组图层
          this.layerManager.layers.value.splice(groupIndex, 1);
        }
      }

      if (this.fabricImage) {
        console.log(`↩️ 移除抠图图像: ${this.fabricImage.id}`);
        // 从画布中移除抠图图像
        this.canvas.remove(this.fabricImage);
      }

      // 2. 逆序撤销所有已执行的子命令
      for (let i = this.executedCommands.length - 1; i >= 0; i--) {
        const command = this.executedCommands[i];
        if (command && typeof command.undo === "function") {
          try {
            console.log(`↩️ 撤销子命令: ${command.constructor.name}`);
            await command.undo();
            console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
          } catch (error) {
            console.error(
              `❌ 子命令撤销失败: ${command.constructor.name}`,
              error
            );
            // 子命令撤销失败不中断整个撤销过程
          }
        }
      }

      // 3. 清理状态
      this.executedCommands = [];
      this.newLayerId = null;
      this.cutoutImageUrl = null;
      this.fabricImage = null;
      this.groupLayer = null; // 清理组图层引用
      // 注意：不重置groupId，因为重做时可能需要使用相同的ID

      // 4. 更新画布和图层交互性
      await this.layerManager.updateLayersObjectsInteractivity(true);

      console.log(`✅ 套索抠图撤销完成`);
      return true;
    } catch (error) {
      console.error("❌ 撤销套索抠图失败:", error);
      return false;
    }
  }

  /**
   * 获取命令信息
   * @returns {Object} 命令详细信息
   */
  getInfo() {
    return {
      name: this.name,
      description: this.description,
      newLayerId: this.newLayerId,
      newLayerName: this.newLayerName,
      groupId: this.groupId,
      groupName: this.groupName,
      executedCommandsCount: this.executedCommands.length,
      hasGroupLayer: !!this.groupLayer,
      sourceLayerId: this.sourceLayerId,
      highResolutionEnabled: this.highResolutionEnabled,
      baseResolutionScale: this.baseResolutionScale,
      hasSerializedSelection: !!this.serializedSelectionObject,
      selectionType: this.serializedSelectionObject?.type || null,
      subCommands: this.executedCommands.map((cmd) => ({
        name: cmd.constructor.name,
        info: cmd.getInfo ? cmd.getInfo() : {},
      })),
    };
  }

  /**
   * 获取图层的所有对象（包括子图层，从画布中查找真实对象）
   * @param {Object} layer 图层对象
   * @returns {Array} 真实的fabric对象数组
   * @private
   */
  _getLayerObjects(layer) {
    const objects = [];
    const canvasObjects = this.canvas.getObjects();

    // 递归获取图层及其子图层的所有对象
    const collectLayerObjects = (currentLayer) => {
      // 处理图层的fabricObjects
      if (
        currentLayer.fabricObjects &&
        Array.isArray(currentLayer.fabricObjects)
      ) {
        currentLayer.fabricObjects.forEach((fabricRef) => {
          if (fabricRef && fabricRef.id) {
            // 从画布中查找真实的对象
            const realObject = canvasObjects.find(
              (obj) => obj.id === fabricRef.id
            );
            if (realObject && realObject.visible) {
              objects.push(realObject);
            }
          }
        });
      }

      // 处理单个fabricObject（背景图层等）
      if (currentLayer.fabricObject && currentLayer.fabricObject.id) {
        const realObject = canvasObjects.find(
          (obj) => obj.id === currentLayer.fabricObject.id
        );
        if (realObject && realObject.visible) {
          objects.push(realObject);
        }
      }

      // 递归处理子图层
      if (currentLayer.children && Array.isArray(currentLayer.children)) {
        currentLayer.children.forEach((childLayer) => {
          if (childLayer.visible !== false) {
            // 只处理可见的子图层
            collectLayerObjects(childLayer);
          }
        });
      }
    };

    collectLayerObjects(layer);

    console.log(`从图层 "${layer.name}" 收集到 ${objects.length} 个可见对象`);
    return objects;
  }

  /**
   * 使用createRasterizedImage执行抠图操作
   * @param {Array} sourceObjects 源对象数组
   * @param {Object} selectionObject 选区对象
   * @param {Object} selectionBounds 选区边界
   * @returns {String} 抠图结果的DataURL
   * @private
   */
  async _performCutoutWithRasterized(
    sourceObjects,
    selectionObject,
    selectionBounds
  ) {
    try {
      console.log("=== 开始使用createRasterizedImage执行抠图 ===");
      console.log(`源对象数量: ${sourceObjects.length}`);
      console.log(`选区边界:`, selectionBounds);

      // 确定缩放因子，确保高质量输出
      let scaleFactor = this.baseResolutionScale;
      if (this.highResolutionEnabled) {
        const devicePixelRatio = window.devicePixelRatio || 1;
        scaleFactor = Math.max(scaleFactor, devicePixelRatio * 1.5);
      }

      // 使用createRasterizedImage生成栅格化图像，将选区作为裁剪路径
      const rasterizedDataURL = await createRasterizedImage({
        canvas: this.canvas,
        fabricObjects: sourceObjects,
        clipPath: selectionObject, // 使用选区作为裁剪路径
        trimWhitespace: true,
        trimPadding: 2,
        quality: 1.0,
        format: "png",
        scaleFactor: scaleFactor,
        // isReturenDataURL: true, // 返回DataURL
        preserveOriginalQuality: true, // 启用高质量模式
        selectionManager: this.selectionManager, // 传递选区管理器，用于获取羽化值
      });

      if (!rasterizedDataURL) {
        throw new Error("栅格化生成图像失败");
      }

      console.log(`✅ 高质量抠图完成，缩放因子: ${scaleFactor}x`);
      return rasterizedDataURL;
    } catch (error) {
      console.error("使用createRasterizedImage执行抠图失败:", error);

      // 如果createRasterizedImage失败，回退到原始方法
      console.log("⚠️ 回退到原始抠图方法...");
      return await this._performCutout(
        { fabricObjects: sourceObjects },
        selectionObject
      );
    }
  }

  /**
   * 原始抠图方法（作为备用方案）
   * @param {Object} sourceLayer 源图层
   * @param {Object} selectionObject 选区对象
   * @returns {String} 抠图结果的DataURL
   * @private
   */
  async _performCutout(sourceLayer, selectionObject) {
    try {
      console.log("=== 使用原始方法执行抠图 ===");

      // 获取选区边界
      const selectionBounds = selectionObject.getBoundingRect(true, true);

      // 保存画布当前状态
      const originalActiveObject = this.canvas.getActiveObject();
      const originalSelection = this.canvas.selection;

      // 临时禁用画布选择
      this.canvas.selection = false;
      this.canvas.discardActiveObject();

      let tempGroup = null;
      let originalObjects = [];

      try {
        // 收集源图层中的可见对象
        const visibleObjects = sourceLayer.fabricObjects.filter(
          (obj) => obj.visible
        );

        if (visibleObjects.length === 0) {
          throw new Error("源图层没有可见对象");
        }

        // 如果只有一个对象且已经是组，直接使用
        if (visibleObjects.length === 1 && visibleObjects[0].type === "group") {
          tempGroup = visibleObjects[0];
        } else {
          // 创建临时组
          const clonedObjects = [];
          for (const obj of visibleObjects) {
            const cloned = await this._cloneObject(obj);
            clonedObjects.push(cloned);
          }

          tempGroup = new fabric.Group(clonedObjects, {
            selectable: false,
            evented: false,
          });

          this.canvas.add(tempGroup);
        }

        // 设置选区为裁剪路径
        const clipPath = await this._cloneObject(selectionObject);
        clipPath.set({
          fill: "",
          stroke: "",
          absolutePositioned: true,
          originX: "left",
          originY: "top",
        });

        tempGroup.set({
          clipPath: clipPath,
        });

        this.canvas.renderAll();

        // 计算渲染区域
        const renderBounds = {
          left: selectionBounds.left,
          top: selectionBounds.top,
          width: selectionBounds.width,
          height: selectionBounds.height,
        };

        // 设置高分辨率倍数
        let highResolutionScale = 1;
        if (this.highResolutionEnabled) {
          const devicePixelRatio = window.devicePixelRatio || 1;
          highResolutionScale = Math.max(
            this.baseResolutionScale,
            devicePixelRatio * 2
          );
        }

        // 创建用于导出的高分辨率canvas
        const exportCanvas = document.createElement("canvas");
        const exportCtx = exportCanvas.getContext("2d", {
          alpha: true,
          willReadFrequently: false,
          colorSpace: "srgb",
        });

        const actualWidth = Math.round(
          renderBounds.width * highResolutionScale
        );
        const actualHeight = Math.round(
          renderBounds.height * highResolutionScale
        );

        exportCanvas.width = actualWidth;
        exportCanvas.height = actualHeight;
        exportCanvas.style.width = renderBounds.width + "px";
        exportCanvas.style.height = renderBounds.height + "px";

        exportCtx.imageSmoothingEnabled = true;
        exportCtx.imageSmoothingQuality = "high";
        exportCtx.clearRect(0, 0, actualWidth, actualHeight);

        const vpt = this.canvas.viewportTransform;
        const zoom = this.canvas.getZoom();

        exportCtx.save();
        exportCtx.scale(highResolutionScale, highResolutionScale);
        exportCtx.translate(-renderBounds.left, -renderBounds.top);

        if (zoom !== 1 || vpt[4] !== 0 || vpt[5] !== 0) {
          exportCtx.transform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
        }

        tempGroup.render(exportCtx);
        exportCtx.restore();

        const dataUrl = exportCanvas.toDataURL("image/png", 1.0);
        return dataUrl;
      } finally {
        // 清理和恢复
        if (tempGroup) {
          tempGroup.set({ clipPath: null });
          if (originalObjects.length > 0) {
            this.canvas.remove(tempGroup);
          }
        }

        this.canvas.selection = originalSelection;
        if (originalActiveObject) {
          this.canvas.setActiveObject(originalActiveObject);
        }
        this.canvas.renderAll();
      }
    } catch (error) {
      console.error("原始方法执行抠图失败:", error);
      return null;
    }
  }

  /**
   * 从DataURL创建fabric图像对象
   * @param {String} dataUrl 图像DataURL
   * @param {Object} selectionBounds 选区边界信息
   * @returns {fabric.Image} fabric图像对象
   * @private
   */
  async _createFabricImage(dataUrl, selectionBounds) {
    return new Promise((resolve, reject) => {
      fabric.Image.fromURL(
        dataUrl,
        (img) => {
          if (!img) {
            reject(new Error("无法从DataURL创建图像"));
            return;
          }

          // 使用选区的位置作为图像位置
          let targetLeft = selectionBounds.left + selectionBounds.width / 2;
          let targetTop = selectionBounds.top + selectionBounds.height / 2;

          // 设置图像属性，保持选区的原始尺寸
          img.set({
            left: targetLeft,
            top: targetTop,
            originX: "center",
            originY: "center",
            selectable: true,
            evented: true,
            hasControls: true,
            hasBorders: true,
            cornerStyle: "circle",
            cornerColor: "#007aff",
            cornerSize: 10,
            transparentCorners: false,
            borderColor: "#007aff",
            borderScaleFactor: 2,
            // 优化图像渲染质量
            objectCaching: false, // 禁用缓存以确保最佳质量
            statefullCache: true,
            noScaleCache: false,
          });

          // 更新坐标
          img.setCoords();

          console.log(
            `图像创建完成，位置: (${targetLeft}, ${targetTop}), 尺寸: ${img.width}x${img.height}`
          );
          resolve(img);
        },
        {
          crossOrigin: "anonymous",
          // 确保图像以最高质量加载
          quality: 1.0,
        }
      );
    });
  }

  /**
   * 克隆fabric对象
   * @param {Object} obj fabric对象
   * @returns {Object} 克隆的对象
   * @private
   */
  async _cloneObject(obj) {
    return new Promise((resolve, reject) => {
      if (!obj) {
        reject(new Error("对象无效，无法克隆"));
        return;
      }

      try {
        obj.clone((cloned) => {
          if (cloned) {
            resolve(cloned);
          } else {
            reject(new Error("对象克隆失败"));
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 序列化选区对象
   * @private
   */
  _serializeSelectionObject() {
    try {
      if (!this.selectionManager) {
        console.warn("选区管理器不存在，无法序列化选区对象");
        return;
      }

      const selectionObject = this.selectionManager.getSelectionObject();
      if (!selectionObject) {
        console.warn("当前没有选区对象，无法序列化");
        return;
      }

      // 将选区对象转换为可序列化的对象
      this.serializedSelectionObject = selectionObject.toObject([
        "id",
        "layerId",
        "layerName",
        "parentId",
      ]);

      console.log("选区对象已序列化保存");
    } catch (error) {
      console.error("序列化选区对象失败:", error);
      this.serializedSelectionObject = null;
    }
  }

  /**
   * 反序列化选区对象
   * @returns {Promise<Object>} 选区对象
   * @private
   */
  async _getSelectionObject() {
    try {
      // 优先使用克隆的选区对象
      if (this._clonedSelectionObject) {
        console.log("使用克隆的选区对象");
        return await this._cloneObject(this._clonedSelectionObject);
      }

      // 尝试从选区管理器获取当前选区
      const currentSelection = this.selectionManager.getSelectionObject();
      if (currentSelection) {
        console.log("从选区管理器获取到当前选区");
        return currentSelection;
      }

      // 最后使用序列化数据恢复（备用方案）
      if (!this.serializedSelectionObject) {
        console.error("没有可用的选区对象数据");
        return null;
      }

      console.log("从序列化数据恢复选区对象");

      // 根据选区对象类型进行反序列化
      return new Promise((resolve, reject) => {
        const objectType = this.serializedSelectionObject.type;

        if (objectType === "path") {
          fabric.Path.fromObject(this.serializedSelectionObject, (path) => {
            if (path) {
              console.log("路径选区对象反序列化成功");
              resolve(path);
            } else {
              reject(new Error("路径选区对象反序列化失败"));
            }
          });
        } else if (objectType === "polygon") {
          fabric.Polygon.fromObject(
            this.serializedSelectionObject,
            (polygon) => {
              if (polygon) {
                console.log("多边形选区对象反序列化成功");
                resolve(polygon);
              } else {
                reject(new Error("多边形选区对象反序列化失败"));
              }
            }
          );
        } else if (objectType === "rect") {
          fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => {
            if (rect) {
              console.log("矩形选区对象反序列化成功");
              resolve(rect);
            } else {
              reject(new Error("矩形选区对象反序列化失败"));
            }
          });
        } else if (objectType === "ellipse" || objectType === "circle") {
          fabric.Ellipse.fromObject(
            this.serializedSelectionObject,
            (ellipse) => {
              if (ellipse) {
                console.log("椭圆选区对象反序列化成功");
                resolve(ellipse);
              } else {
                reject(new Error("椭圆选区对象反序列化失败"));
              }
            }
          );
        } else {
          // 通用对象反序列化
          fabric.util.enlivenObjects(
            [this.serializedSelectionObject],
            (objects) => {
              if (objects && objects.length > 0) {
                console.log("通用选区对象反序列化成功");
                resolve(objects[0]);
              } else {
                reject(new Error("通用选区对象反序列化失败"));
              }
            }
          );
        }
      });
    } catch (error) {
      console.error("获取选区对象失败:", error);
      return null;
    }
  }
}
