import { generateId } from "../utils/helper";
import { createLayer, findLayerRecursively, LayerType, OperationType } from "../utils/layerHelper";
import { Command } from "./Command";
import {
  findObjectById,
  removeCanvasObjectByObject,
  optimizeCanvasRendering,
} from "../utils/helper";
import { fabric } from "fabric-with-all";
import { rasterizeCanvasObjects } from "../utils/imageHelper";

/**
 * 合并组图层命令 - 将图层及其子图层合并为单个图层
 */
export class MergeGroupLayerCommand extends Command {
  constructor(options) {
    super({
      name: "合并组图层为单个图层",
      saveState: true,
    });
    this.canvas = options.canvas;
    this.layers = options.layers;
    this.layerId = options.layerId;
    this.activeLayerId = options.activeLayerId;
    this.layerManager = options.layerManager;

    this.originalLayers = [...this.layers.value];
    this.originalObjects = [...this.canvas.getObjects()];
    this.flattenedLayer = null;
    this.flattenedLayerId =
      generateId("flattened_") || `flattened_${Date.now()}_${Math.floor(Math.random() * 1000)}`;

    this.existingGroupId = null; // 用于查找现有组对象
    // 组对象相关
    this.newGroupId =
      generateId("group") || `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
  }

  async execute() {
    // 查找源图层
    const { layer } = findLayerRecursively(this.layers.value, this.layerId);
    const sourceLayer = layer;
    if (!sourceLayer) {
      console.error(`图层 ${this.layerId} 不存在`);
      return null;
    }

    // 收集要展平的图层（包括子图层）
    const layersToFlatten = this._collectLayersToFlatten(sourceLayer);

    if (layersToFlatten.length === 0) {
      console.warn("没有找到可展平的图层");
      return null;
    }

    // 收集所有图层的fabricObjects
    const allLayerObjects = [];
    layersToFlatten.forEach((layer) => {
      if (layer.fabricObjects && layer.fabricObjects.length > 0) {
        allLayerObjects.push(...layer.fabricObjects);
      }
    });

    if (allLayerObjects.length === 0) {
      console.warn("图层中没有fabricObjects");
      return null;
    }

    // 在画布中查找这些对象对应的真实Canvas对象
    const canvasObjects = [];
    const originalObjectStates = new Map(); // 保存对象的原始状态

    allLayerObjects.forEach((layerObj) => {
      if (layerObj && layerObj.id) {
        const { object } = findObjectById(this.canvas, layerObj.id);
        if (object) {
          // 深度克隆对象状态，避免引用问题
          const originalState = {
            left: object.left,
            top: object.top,
            scaleX: object.scaleX,
            scaleY: object.scaleY,
            angle: object.angle,
            flipX: object.flipX,
            flipY: object.flipY,
            opacity: object.opacity,
            originX: object.originX,
            originY: object.originY,
            layerId: object.layerId,
            layerName: object.layerName,
            // 保存其他重要属性
            width: object.width,
            height: object.height,
            strokeWidth: object.strokeWidth,
            visible: object.visible,
          };
          originalObjectStates.set(object.id, originalState);

          canvasObjects.unshift(object);
          // 从画布中移除原对象，准备重新组织
          removeCanvasObjectByObject(this.canvas, object);
        }
      }
    });

    // 保存原始对象状态到实例变量，供undo使用
    this.originalObjectStates = originalObjectStates;

    if (canvasObjects.length === 0) {
      console.warn("没有找到对应的Canvas对象");
      return null;
    }

    // 根据对象数量决定处理方式
    let finalObjects = [];
    if (canvasObjects.length > 1) {
      // 创建对象的克隆副本用于组合，避免修改原始对象
      const clonedObjects = canvasObjects.map((obj) => {
        return fabric.util.object.clone(obj);
      });

      // 使用克隆的对象创建组
      const group = new fabric.Group(clonedObjects, {
        id: this.newGroupId,
        name: `${sourceLayer.name} (group)`,
        layerId: sourceLayer.id,
        layerName: sourceLayer.name,
        type: "group",
      });

      // 将组对象添加到画布
      this.canvas.add(group);
      this.canvas.setActiveObject(group);
      this.existingGroupId = group.id;
      finalObjects = [group];

      console.log(`已创建组对象，包含 ${canvasObjects.length} 个子对象`);
    } else {
      // 单个对象，创建副本避免修改原始对象
      const clonedObject = fabric.util.object.clone(canvasObjects[0]);

      // 重新添加到画布
      this.canvas.add(clonedObject);
      this.canvas.setActiveObject(clonedObject);
      finalObjects = [clonedObject];

      console.log("单个对象，已更新关联关系");
    }

    // 创建展平后的图层
    this.flattenedLayer = createLayer({
      id: this.flattenedLayerId,
      name: `${sourceLayer.name} (merged)`,
      type: LayerType.BITMAP,
      visible: sourceLayer.visible,
      locked: false,
      opacity: sourceLayer.opacity,
      fabricObjects: finalObjects,
    });

    // 更新对象关联
    finalObjects.forEach((obj) => {
      obj.layerId = this.flattenedLayerId;
      obj.layerName = this.flattenedLayer.name;
    });

    // 获取源图层在数组中的索引
    const sourceIndex = this.layers.value.findIndex((l) => l.id === this.layerId);

    // 移除所有相关图层
    const layerIdsToRemove = layersToFlatten.map((layer) => layer.id);
    this.layers.value = this.layers.value.filter((layer) => !layerIdsToRemove.includes(layer.id));

    // 在原位置插入展平后的图层
    this.layers.value.splice(sourceIndex, 0, this.flattenedLayer);

    // 设置为活动图层
    this.activeLayerId.value = this.flattenedLayerId;

    // 重新渲染画布
    // await optimizeCanvasRendering(this.canvas, () => {
    //   this.canvas.renderAll();
    // });

    await this.layerManager?.updateLayersObjectsInteractivity(false);

    this.canvas?.thumbnailManager?.generateLayerThumbnail?.(this.newGroupId);

    console.log(`已合并图层：${this.flattenedLayer.name}`);
    return this.flattenedLayerId;
  }

  async undo() {
    if (!this.flattenedLayer || !this.originalLayers || !this.originalObjectStates) {
      console.warn("没有可撤销的数据");
      return;
    }

    try {
      await optimizeCanvasRendering(this.canvas, async () => {
        this.canvas.discardActiveObject();
        this.canvas.clear();

        // 恢复原始对象及其状态
        this.originalObjects.forEach((obj) => {
          // 如果保存了该对象的原始状态，则恢复状态
          if (this.originalObjectStates.has(obj.id)) {
            const originalState = this.originalObjectStates.get(obj.id);
            obj.set(originalState);
          }

          this.canvas.add(obj);
          obj.setCoords();
        });

        // 恢复原始图层结构
        this.layers.value = [...this.originalLayers];

        // 恢复原活动图层
        this.activeLayerId.value = this.layerId;

        // 更新画布交互性
        await this.layerManager?.updateLayersObjectsInteractivity(false);

        console.log("✅ 成功撤销组图层合并操作");
      });
    } catch (error) {
      console.error("撤销组图层合并时发生错误:", error);
    }
  }

  /**
   * 查找当前合并后的对象
   * @returns {Object} 包含对象信息的结果
   * @private
   */
  _findMergedObjects() {
    const objects = [];

    // 查找合并后的图层中的对象
    if (this.flattenedLayer?.fabricObjects) {
      this.flattenedLayer.fabricObjects.forEach((layerObj) => {
        if (layerObj?.id) {
          const { object } = findObjectById(this.canvas, layerObj.id);
          if (object) {
            objects.push({
              canvasObject: object,
              layerObject: layerObj,
              isGroup: object.type === "group",
            });
          }
        }
      });
    }

    return { objects };
  }

  /**
   * 拆解合并的对象（组对象或单个对象）
   * @param {Object} mergedObjectResult 合并对象结果
   * @private
   */
  async _unmergeMergedObjects(mergedObjectResult) {
    const restoredObjects = [];

    for (const objInfo of mergedObjectResult.objects) {
      const { canvasObject, isGroup } = objInfo;

      if (isGroup) {
        // 拆解组对象
        const ungroupedObjects = await this._ungroupObject(canvasObject);
        restoredObjects.push(...ungroupedObjects);
      } else {
        // 单个对象直接保留，但需要清除合并相关的属性
        this._clearMergedObjectProperties(canvasObject);
        restoredObjects.push(canvasObject);
      }

      // 从画布中移除原对象
      removeCanvasObjectByObject(this.canvas, canvasObject);
    }

    // 将拆解后的对象重新添加到画布
    restoredObjects.forEach((obj) => {
      if (obj && !this.canvas.getObjects().includes(obj)) {
        this.canvas.add(obj);
      }
    });

    return restoredObjects;
  }

  /**
   * 拆解组对象为单个对象
   * @param {fabric.Group} groupObject 组对象
   * @returns {Array} 拆解后的对象数组
   * @private
   */
  async _ungroupObject(groupObject) {
    if (!groupObject || groupObject.type !== "group") {
      return [];
    }

    const ungroupedObjects = [];
    const groupObjects = groupObject.getObjects() || [];

    // 逐个拆解组内对象
    groupObjects.forEach((obj) => {
      try {
        // 计算对象的绝对位置
        const absolutePosition = this._calculateObjectAbsolutePosition(obj, groupObject);

        // 使用removeWithUpdate移除对象，这会自动恢复对象的独立状态
        groupObject.removeWithUpdate(obj);

        // 应用计算出的绝对位置
        obj.set({
          left: absolutePosition.left,
          top: absolutePosition.top,
          scaleX: absolutePosition.scaleX,
          scaleY: absolutePosition.scaleY,
          angle: absolutePosition.angle,
          originX: absolutePosition.originX || "center",
          originY: absolutePosition.originY || "center",
          flipX: absolutePosition.flipX || false,
          flipY: absolutePosition.flipY || false,
          opacity: absolutePosition.opacity || 1,
          selectable: true,
          evented: true,
        });

        // 更新对象坐标
        obj.setCoords();

        ungroupedObjects.push(obj);

        console.log(
          `📤 拆解组内对象: ${obj.id || obj.type} 到位置 (${
            absolutePosition.left
          }, ${absolutePosition.top})`
        );
      } catch (error) {
        console.error(`拆解组内对象时发生错误:`, error);
      }
    });

    return ungroupedObjects;
  }

  /**
   * 计算对象在画布中的绝对位置
   * @param {fabric.Object} obj 组内对象
   * @param {fabric.Group} group 组对象
   * @returns {Object} 绝对位置信息
   * @private
   */
  _calculateObjectAbsolutePosition(obj, group) {
    try {
      // 获取组的变换矩阵
      const groupTransform = group.calcTransformMatrix();

      // 获取对象在组内的相对位置
      const objectPoint = new fabric.Point(obj.left || 0, obj.top || 0);

      // 应用组的变换矩阵计算绝对位置
      const absolutePoint = fabric.util.transformPoint(objectPoint, groupTransform);

      // 计算缩放比例
      const totalScaleX = (group.scaleX || 1) * (obj.scaleX || 1);
      const totalScaleY = (group.scaleY || 1) * (obj.scaleY || 1);

      // 计算总旋转角度
      const totalAngle = (group.angle || 0) + (obj.angle || 0);

      return {
        left: absolutePoint.x,
        top: absolutePoint.y,
        scaleX: totalScaleX,
        scaleY: totalScaleY,
        angle: totalAngle,
        flipX: obj.flipX || false,
        flipY: obj.flipY || false,
        originX: obj.originX || "center",
        originY: obj.originY || "center",
        opacity: obj.opacity || 1,
      };
    } catch (error) {
      console.warn("使用变换矩阵计算位置失败，使用简化计算:", error);

      // 备选方案：基于组的中心点和对象的相对偏移计算
      const groupCenterX = group.left || 0;
      const groupCenterY = group.top || 0;

      const scaleX = group.scaleX || 1;
      const scaleY = group.scaleY || 1;
      const angle = group.angle || 0;

      const offsetX = (obj.left || 0) * scaleX;
      const offsetY = (obj.top || 0) * scaleY;

      let finalX = groupCenterX + offsetX;
      let finalY = groupCenterY + offsetY;

      if (angle !== 0) {
        const cos = Math.cos(fabric.util.degreesToRadians(angle));
        const sin = Math.sin(fabric.util.degreesToRadians(angle));

        finalX = groupCenterX + offsetX * cos - offsetY * sin;
        finalY = groupCenterY + offsetX * sin + offsetY * cos;
      }

      return {
        left: finalX,
        top: finalY,
        scaleX: scaleX * (obj.scaleX || 1),
        scaleY: scaleY * (obj.scaleY || 1),
        angle: angle + (obj.angle || 0),
        flipX: obj.flipX || false,
        flipY: obj.flipY || false,
        originX: obj.originX || "center",
        originY: obj.originY || "center",
        opacity: obj.opacity || 1,
      };
    }
  }

  /**
   * 清除对象的合并相关属性
   * @param {fabric.Object} obj 对象
   * @private
   */
  _clearMergedObjectProperties(obj) {
    if (!obj) return;

    // 重置对象的选择和事件属性
    obj.set({
      selectable: true,
      evented: true,
      opacity: 1,
    });
  }

  /**
   * 恢复对象与图层的关联关系
   * @private
   */
  async _restoreObjectLayerAssociations() {
    // 获取当前画布上的所有对象
    const canvasObjects = this.canvas.getObjects();

    // 遍历原始图层结构，重新建立关联
    const processLayer = (layer) => {
      if (!layer || !layer.fabricObjects) return;

      // 为每个图层对象查找对应的canvas对象并更新关联
      layer.fabricObjects.forEach((layerObj) => {
        if (layerObj?.id) {
          const canvasObj = canvasObjects.find((obj) => obj.id === layerObj.id);
          if (canvasObj) {
            // 恢复对象的图层关联信息
            canvasObj.layerId = layer.id;
            canvasObj.layerName = layer.name;

            console.log(`🔗 恢复对象 ${canvasObj.id} 与图层 ${layer.name} 的关联`);
          }
        }
      });

      // 递归处理子图层
      if (layer.children && Array.isArray(layer.children)) {
        layer.children.forEach((childLayer) => {
          processLayer(childLayer);
        });
      }
    };

    // 处理所有原始图层
    this.originalLayers.forEach((layer) => {
      processLayer(layer);
    });
  }

  _collectLayersToFlatten(sourceLayer) {
    const result = [sourceLayer];

    // 如果是组图层，收集所有子图层
    if (sourceLayer.children && sourceLayer.children.length > 0) {
      result.push(...sourceLayer.children);

      // 递归收集子图层 - 暂时不支持多层
      // sourceLayer.children.forEach((childLayer) => {
      //   if (childLayer) {
      //     result.push(...this._collectLayersToFlatten(childLayer));
      //   }
      // });
    }

    return result;
  }

  getInfo() {
    return {
      name: this.name,
      sourceLayerId: this.layerId,
      flattenedLayerId: this.flattenedLayerId,
      flattenedLayerName: this.flattenedLayer?.name,
    };
  }
}
