import { ReorderChildLayersCommand } from "../commands/LayerCommands";
import { optimizeCanvasRendering } from "./helper";
import { findLayerRecursively, LayerType } from "./layerHelper";

/**
 * 图层排序工具类
 * 提供图层排序、重新排列画布对象等功能
 * 基于fabric.js 5.3.1版本开发
 */
export class LayerSort {
  /**
   * 构造函数
   * @param {Object} canvas fabric.js画布实例
   * @param {Object} layers 图层数组响应式引用
   */
  constructor(canvas, layers, options = {}) {
    this.canvas = canvas;
    this.layers = layers;
    this.commandManager = options.commandManager || null; // 命令管理器（可选）
  }

  /**
   * 重新排列画布上的对象以匹配图层顺序
   * 使用 fabric.js 的 moveTo 方法直接调整对象层级，无需清空画布
   */
  async rearrangeObjects() {
    if (!this.canvas) return;

    const canvasObjects = this.canvas.getObjects();
    if (canvasObjects.length === 0) return;

    // 使用画布渲染优化
    await optimizeCanvasRendering(this.canvas, () => {
      // 计算每个对象应该在的 z-index 位置
      const objectZIndexMap = this.calculateObjectZIndexes();

      // 按照新的 z-index 排序对象
      const sortedObjects = canvasObjects
        .map((obj) => ({
          object: obj,
          targetZIndex: objectZIndexMap.get(obj.id) ?? -1,
        }))
        .filter((item) => item.targetZIndex >= 0) // 过滤掉无效对象
        .sort((a, b) => a.targetZIndex - b.targetZIndex);

      // 使用 fabric.js 的 moveTo 方法重新排序
      sortedObjects.forEach((item, index) => {
        const currentIndex = this.canvas.getObjects().indexOf(item.object);
        if (currentIndex !== index && currentIndex !== -1) {
          // 将对象移动到正确的位置
          this.canvas.moveTo(item.object, index);
        }
      });
    });
  }

  /**
   * 计算每个对象在画布中应该的 z-index
   * 考虑图层类型、组结构和子图层
   * @returns {Map} 对象ID到z-index的映射
   */
  calculateObjectZIndexes() {
    const zIndexMap = new Map();
    let currentZIndex = 0;

    // 按照图层在数组中的顺序从后往前遍历（数组末尾 = 画布底层）
    for (let i = this.layers.value.length - 1; i >= 0; i--) {
      const layer = this.layers.value[i];

      // 跳过不可见图层
      // if (!layer.visible) {
      //   continue;
      // }

      // 处理不同类型的图层
      if (layer.isBackground && layer.fabricObject) {
        // 背景图层对象放在最底层
        zIndexMap.set(layer.fabricObject.id, currentZIndex++);
      } else if (layer.isFixed && layer.fabricObject) {
        // 固定图层对象
        zIndexMap.set(layer.fabricObject.id, currentZIndex++);
      } else if (layer.isFixedOther && layer.fabricObject) {
        // 其他固定图层对象
        zIndexMap.set(layer.fabricObject.id, currentZIndex++);
      } else if (!layer.isBackground && !layer.isFixed) {
        // 普通图层
        currentZIndex = this.processLayerObjects(
          layer,
          currentZIndex,
          zIndexMap
        );
      }
    }

    return zIndexMap;
  }

  /**
   * 处理图层对象，包括组和子图层的情况
   * @param {Object} layer 图层对象
   * @param {number} currentZIndex 当前z-index
   * @param {Map} zIndexMap z-index映射表
   * @returns {number} 更新后的z-index
   */
  processLayerObjects(layer, currentZIndex, zIndexMap) {
    // if (layer.fill) {
    //   // 如果图层有填充，则填充在最底层
    //   zIndexMap.set(layer.fill.id, currentZIndex++);
    // }
    // 检查是否有子图层（组图层）
    if (layer.children?.length > 0) {
      // 处理每个子图层
      // 按照图层在数组中的顺序从后往前遍历（数组末尾 = 画布底层）
      for (let i = layer.children.length - 1; i >= 0; i--) {
        const childLayer = layer.children[i];

        // 跳过不可见图层
        // if (!childLayer.visible) {
        //   continue;
        // }

        for (let j = childLayer.fabricObjects.length - 1; j >= 0; j--) {
          const obj = childLayer.fabricObjects[j];
          if (obj?.id) {
            zIndexMap.set(obj.id, currentZIndex++);
          }
        }
      }
    }

    // 处理图层本身的对象
    if (Array.isArray(layer.fabricObjects)) {
      for (let j = layer.fabricObjects.length - 1; j >= 0; j--) {
        const obj = layer.fabricObjects[j];
        if (obj?.id) {
          zIndexMap.set(obj.id, currentZIndex++);
        }
      }
    }

    return currentZIndex;
  }

  /**
   * 获取指定图层的子图层，按照正确顺序排列
   * @param {string} parentLayerId 父图层ID
   * @returns {Array} 子图层数组
   */
  getChildLayersInOrder(parentLayerId) {
    // 获取所有子图层
    const childLayers =
      this.layers.value.filter((layer) => layer.id === parentLayerId)
        ?.children || [];

    return childLayers;
  }

  /**
   * 根据ID获取图层
   * @param {string} layerId 图层ID
   * @returns {Object|null} 图层对象或null
   */
  getLayerById(layerId) {
    if (!layerId || !this.layers.value) return null;
    return this.layers.value.find((layer) => layer.id === layerId) ?? null;
  }

  /**
   * 批量重新排列对象（异步版本，适用于大量对象）
   * @returns {Promise<void>}
   */
  async rearrangeObjectsAsync() {
    if (!this.canvas) return;

    const canvasObjects = this.canvas.getObjects();
    if (canvasObjects.length === 0) return;

    return new Promise((resolve) => {
      // 使用 requestAnimationFrame 进行异步处理
      requestAnimationFrame(() => {
        this.canvas.renderOnAddRemove = false;

        try {
          const objectZIndexMap = this.calculateObjectZIndexes();

          const sortedObjects = canvasObjects
            .map((obj) => ({
              object: obj,
              targetZIndex: objectZIndexMap.get(obj.id) ?? -1,
            }))
            .filter((item) => item.targetZIndex >= 0)
            .sort((a, b) => a.targetZIndex - b.targetZIndex);

          // 分批处理，避免一次性处理太多对象
          const batchSize = LayerSortConstants.BATCH_SIZE;
          let currentBatch = 0;

          const processBatch = () => {
            const start = currentBatch * batchSize;
            const end = Math.min(start + batchSize, sortedObjects.length);

            for (let i = start; i < end; i++) {
              const item = sortedObjects[i];
              const currentIndex = this.canvas
                .getObjects()
                .indexOf(item.object);
              if (currentIndex !== i && currentIndex !== -1) {
                this.canvas.moveTo(item.object, i);
              }
            }

            currentBatch++;

            if (end < sortedObjects.length) {
              // 继续处理下一批
              requestAnimationFrame(processBatch);
            } else {
              // 所有批次处理完成
              this.canvas.renderOnAddRemove = true;
              this.canvas.renderAll();
              resolve();
            }
          };

          processBatch();
        } catch (error) {
          this.canvas.renderOnAddRemove = true;
          this.canvas.renderAll();
          console.error("重新排列对象时出错:", error);
          resolve();
        }
      });
    });
  }

  /**
   * 验证对象顺序是否正确
   * @returns {boolean} 顺序是否正确
   */
  validateObjectOrder() {
    const canvasObjects = this.canvas.getObjects();
    const objectZIndexMap = this.calculateObjectZIndexes();

    for (let i = 0; i < canvasObjects.length - 1; i++) {
      const currentObj = canvasObjects[i];
      const nextObj = canvasObjects[i + 1];

      const currentZIndex = objectZIndexMap.get(currentObj.id);
      const nextZIndex = objectZIndexMap.get(nextObj.id);

      if (currentZIndex !== undefined && nextZIndex !== undefined) {
        if (currentZIndex > nextZIndex) {
          return false; // 顺序不正确
        }
      }
    }

    return true; // 顺序正确
  }

  /**
   * 图层排序规则：背景图层 > 固定图层 > 普通图层
   * @param {Array} layers 图层数组
   * @returns {Array} 排序后的图层数组
   */
  sortLayers(layers = null) {
    const targetLayers = layers ?? this.layers.value;

    return [...targetLayers].sort((a, b) => {
      // 如果a是背景图层，它应该排在后面（最底层）
      if (a.isBackground) return 1;
      // 如果b是背景图层，它应该排在后面（最底层）
      if (b.isBackground) return -1;

      // 如果a是固定图层而b不是固定图层，a应该排在后面（固定图层在普通图层下方）
      if (a.isFixed && !b.isFixed) return 1;
      // 如果b是固定图层而a不是固定图层，b应该排在后面（固定图层在普通图层下方）
      if (b.isFixed && !a.isFixed) return -1;

      // 其他情况保持原有顺序
      return 0;
    });
  }

  /**
   * 获取图层在排序后的正确插入位置
   * @param {Object} newLayer 新图层
   * @param {string} targetLayerId 目标图层ID（插入到该图层之前）
   * @returns {number} 插入位置索引
   */
  getInsertIndex(newLayer, targetLayerId = null) {
    if (!targetLayerId) {
      // 如果没有指定目标图层，根据图层类型决定插入位置
      if (newLayer.isBackground) {
        return this.layers.value.length; // 背景图层插入到最后
      } else if (newLayer.isFixed) {
        // 固定图层插入到背景图层之前
        const bgIndex = this.layers.value.findIndex(
          (layer) => layer.isBackground
        );
        return bgIndex !== -1 ? bgIndex : this.layers.value.length;
      } else {
        // 普通图层插入到固定图层之前
        const fixedIndex = this.layers.value.findIndex(
          (layer) => layer.isFixed
        );
        return fixedIndex !== -1 ? fixedIndex : this.layers.value.length;
      }
    }

    // 如果指定了目标图层，插入到目标图层之前
    const targetIndex = this.layers.value.findIndex(
      (layer) => layer.id === targetLayerId
    );
    return targetIndex !== -1 ? targetIndex : this.layers.value.length;
  }

  /**
   * 移动图层到指定位置
   * @param {string} layerId 要移动的图层ID
   * @param {number} newIndex 新位置索引
   * @returns {boolean} 是否移动成功
   */
  async moveLayerToIndex({ parentId, oldIndex, newIndex, layerId }) {
    // 检查父图层是否存在
    // const parentLayer = this.getLayerById(parentId);
    const { layer: childLayer, parent: parentLayer } = findLayerRecursively(
      this.layers.value,
      layerId,
      parentId
    );

    if (!parentLayer) {
      console.warn(`父图层 ${parentId} 不存在`);
      return false;
    }

    // 获取所有子图层
    const childLayers = parentLayer?.children || [];

    // 检查索引有效性
    if (
      oldIndex < 0 ||
      newIndex < 0 ||
      oldIndex >= childLayers.length ||
      newIndex >= childLayers.length
    ) {
      console.warn("子图层排序索引无效");
      return false;
    }

    // 检查是否是同一位置
    if (oldIndex === newIndex) {
      return true;
    }

    // 验证图层ID
    const layer = childLayers[oldIndex];
    if (!layer || layer.id !== layerId) {
      console.warn("子图层ID与索引不匹配");
      return false;
    }

    // 更新父图层的children数组  -  执行命令
    const command = new ReorderChildLayersCommand({
      parentId,
      oldIndex,
      newIndex,
      layerId,
      layers: this.layers,
      canvas: this.canvas,
      layerSort: this, // 传入当前实例
    });

    if (this.commandManager) {
      await this.commandManager?.execute(command);
    } else {
      await command?.execute?.();
    }

    return true;
  }

  /**
   * 获取图层的有效移动范围
   * @param {string} layerId 图层ID
   * @returns {Object} 包含最小和最大索引的对象
   */
  getLayerMoveRange(layerId) {
    const layer = this.getLayerById(layerId);
    if (!layer || layer.isBackground || layer.isFixed) {
      return { minIndex: -1, maxIndex: -1 };
    }

    // 普通图层只能在普通图层范围内移动
    const normalLayers = this.layers.value
      .map((layer, index) => ({ layer, index }))
      .filter((item) => !item.layer.isBackground && !item.layer.isFixed);

    if (normalLayers.length === 0) {
      return { minIndex: -1, maxIndex: -1 };
    }

    return {
      minIndex: normalLayers[0].index,
      maxIndex: normalLayers[normalLayers.length - 1].index,
    };
  }

  /**
   * 拖拽排序图层
   * @param {number} oldIndex 原索引
   * @param {number} newIndex 新索引
   * @param {string} layerId 图层ID
   * @returns {boolean} 是否排序成功
   */
  async reorderLayers(oldIndex, newIndex, layerId) {
    // 检查索引有效性
    if (
      oldIndex < 0 ||
      newIndex < 0 ||
      oldIndex >= this.layers.value.length ||
      newIndex >= this.layers.value.length
    ) {
      console.warn("图层排序索引无效");
      return false;
    }

    // 检查是否是同一位置
    if (oldIndex === newIndex) {
      return true;
    }

    // 获取要移动的图层
    const layer = this.layers.value[oldIndex];
    if (!layer || layer.id !== layerId) {
      console.warn("图层ID与索引不匹配");
      return false;
    }

    // 检查是否是背景层或固定层（不允许排序）
    if (layer.isBackground || layer.isFixed) {
      console.warn("背景层和固定层不能参与排序");
      return false;
    }

    // 检查目标位置是否合法（不能移到背景层或固定层的位置）
    const targetLayer = this.layers.value[newIndex];
    if (targetLayer && (targetLayer.isBackground || targetLayer.isFixed)) {
      console.warn("不能移动到背景层或固定层的位置");
      return false;
    }

    // 执行排序
    const layersArray = [...this.layers.value];
    const [movedLayer] = layersArray.splice(oldIndex, 1);
    layersArray.splice(newIndex, 0, movedLayer);

    this.layers.value = layersArray;

    // 重新排列画布对象
    await this.rearrangeObjects();

    return true;
  }

  /**
   * 子图层排序
   * @param {string} parentId 父图层ID
   * @param {number} oldIndex 原索引
   * @param {number} newIndex 新索引
   * @param {string} layerId 子图层ID
   * @returns {boolean} 是否排序成功
   */
  async reorderChildLayers(parentId, oldIndex, newIndex, layerId) {
    // 检查父图层是否存在
    // const parentLayer = this.getLayerById(parentId);
    const { layer: childLayer, parent: parentLayer } = findLayerRecursively(
      this.layers.value,
      layerId,
      parentId
    );

    if (!parentLayer) {
      console.warn(`父图层 ${parentId} 不存在`);
      return false;
    }

    // 获取所有子图层
    const childLayers = parentLayer?.children || [];

    // 检查索引有效性
    if (
      oldIndex < 0 ||
      newIndex < 0 ||
      oldIndex >= childLayers.length ||
      newIndex >= childLayers.length
    ) {
      console.warn("子图层排序索引无效");
      return false;
    }

    // 检查是否是同一位置
    if (oldIndex === newIndex) {
      return true;
    }

    // 验证图层ID
    const layer = childLayers[oldIndex];
    if (!layer || layer.id !== layerId) {
      console.warn("子图层ID与索引不匹配");
      return false;
    }

    // 更新父图层的children数组  -  执行命令
    const command = ReorderChildLayersCommand({
      parentId,
      oldIndex,
      newIndex,
      layerId,
      layers: this.layers,
      canvas: this.canvas,
      layerSort: this, // 传入当前实例
    });

    if (this.commandManager) {
      await this.commandManager?.execute(command);
    } else {
      await command?.execute?.();
    }
    return true;
  }

  /**
   * 智能排序 - 根据对象类型和位置自动调整图层顺序
   * @param {Array} targetLayerIds 要排序的图层ID数组
   * @returns {boolean} 是否排序成功
   */
  async smartSort(targetLayerIds = null) {
    const layersToSort = targetLayerIds
      ? this.layers.value.filter((layer) => targetLayerIds.includes(layer.id))
      : this.layers.value.filter(
          (layer) => !layer.isBackground && !layer.isFixed
        );

    if (layersToSort.length <= 1) return true;

    // 按照对象类型和位置进行智能排序
    layersToSort.sort((a, b) => {
      const aWeight = this.getLayerSortWeight(a);
      const bWeight = this.getLayerSortWeight(b);

      if (aWeight !== bWeight) {
        return bWeight - aWeight; // 权重高的在上层
      }

      // 权重相同时，按照Y坐标排序（Y值小的在上层）
      const aY = this.getLayerAverageY(a);
      const bY = this.getLayerAverageY(b);

      return aY - bY;
    });

    // 更新图层顺序
    const sortedLayerIds = layersToSort.map((layer) => layer.id);
    const otherLayers = this.layers.value.filter(
      (layer) => !sortedLayerIds.includes(layer.id)
    );

    // 重新组织图层数组：保持背景层和固定层的位置
    const newLayers = [];

    // 添加普通图层（已排序）
    newLayers.push(...layersToSort);

    // 添加其他普通图层
    otherLayers.forEach((layer) => {
      if (!layer.isBackground && !layer.isFixed) {
        newLayers.push(layer);
      }
    });

    // 添加固定图层
    otherLayers.forEach((layer) => {
      if (layer.isFixed) {
        newLayers.push(layer);
      }
    });

    // 添加背景图层
    otherLayers.forEach((layer) => {
      if (layer.isBackground) {
        newLayers.push(layer);
      }
    });

    this.layers.value = newLayers;
    await this.rearrangeObjects();

    return true;
  }

  /**
   * 获取图层的排序权重
   * @param {Object} layer 图层对象
   * @returns {number} 排序权重
   */
  getLayerSortWeight(layer) {
    const weightMap = LayerSortConstants.LAYER_PRIORITY;

    if (layer.isBackground) return weightMap[LayerType.BACKGROUND];
    if (layer.isFixed) return weightMap[LayerType.FIXED];
    if (layer.children?.length > 0) return weightMap[LayerType.GROUP];

    // 根据对象类型调整权重
    if (layer.fabricObjects && layer.fabricObjects.length > 0) {
      const firstObj = layer.fabricObjects[0];
      if (firstObj.type === "text") return weightMap[LayerType.NORMAL] + 10;
      if (firstObj.type === "image") return weightMap[LayerType.NORMAL] + 5;
    }

    return weightMap[LayerType.NORMAL];
  }

  /**
   * 获取图层对象的平均Y坐标
   * @param {Object} layer 图层对象
   * @returns {number} 平均Y坐标
   */
  getLayerAverageY(layer) {
    let totalY = 0;
    let count = 0;

    if (layer.fabricObject) {
      totalY += layer.fabricObject.top || 0;
      count++;
    }

    if (layer.fabricObjects && layer.fabricObjects.length > 0) {
      layer.fabricObjects.forEach((obj) => {
        totalY += obj.top || 0;
        count++;
      });
    }

    return count > 0 ? totalY / count : 0;
  }

  /**
   * 优化图层结构 - 清理空图层、合并相邻相似图层等
   * @returns {Object} 优化结果统计
   */
  async optimizeLayerStructure() {
    const stats = {
      removedEmptyLayers: 0,
      mergedLayers: 0,
      reorderedLayers: 0,
    };

    // 清理空图层
    const emptyLayers = this.layers.value.filter(
      (layer) =>
        !layer.isBackground &&
        !layer.isFixed &&
        (!layer.fabricObjects || layer.fabricObjects.length === 0) &&
        (!layer.children || layer.children.length === 0)
    );

    emptyLayers.forEach((layer) => {
      const index = this.layers.value.findIndex((l) => l.id === layer.id);
      if (index !== -1) {
        this.layers.value.splice(index, 1);
        stats.removedEmptyLayers++;
      }
    });

    // 重新排序以确保正确的层级关系
    const wasReordered = this.sortLayers();
    if (wasReordered) {
      stats.reorderedLayers = this.layers.value.length;
      await this.rearrangeObjects();
    }

    return stats;
  }
}

/**
 * 创建图层排序工具实例
 * @param {Object} canvas fabric.js画布实例
 * @param {Object} layers 图层数组响应式引用
 * @returns {LayerSort} 图层排序工具实例
 */
export const createLayerSort = (canvas, layers, options = {}) => {
  return new LayerSort(canvas, layers, options);
};

/**
 * 图层排序相关的常量
 */
export const LayerSortConstants = {
  // 图层类型优先级（数值越大优先级越高，在画布中越靠上）
  LAYER_PRIORITY: {
    [LayerType.BACKGROUND]: 0,
    [LayerType.FIXED]: 1,
    [LayerType.NORMAL]: 2,
    [LayerType.GROUP]: 2,
  },

  // 批处理大小
  BATCH_SIZE: 50,

  // 性能阈值
  PERFORMANCE_THRESHOLD: {
    OBJECTS_COUNT: 100, // 超过此数量使用异步处理
    LAYERS_COUNT: 20, // 超过此数量使用分批处理
  },
};

/**
 * 图层排序辅助函数
 */
export const LayerSortUtils = {
  /**
   * 检查是否需要异步处理
   * @param {number} objectsCount 对象数量
   * @param {number} layersCount 图层数量
   * @returns {boolean} 是否需要异步处理
   */
  shouldUseAsyncProcessing(objectsCount, layersCount) {
    return (
      objectsCount > LayerSortConstants.PERFORMANCE_THRESHOLD.OBJECTS_COUNT ||
      layersCount > LayerSortConstants.PERFORMANCE_THRESHOLD.LAYERS_COUNT
    );
  },

  /**
   * 获取图层的排序权重
   * @param {Object} layer 图层对象
   * @returns {number} 排序权重
   */
  getLayerSortWeight(layer) {
    if (layer.isBackground)
      return LayerSortConstants.LAYER_PRIORITY[LayerType.BACKGROUND];
    if (layer.isFixed)
      return LayerSortConstants.LAYER_PRIORITY[LayerType.FIXED];
    if (layer.children?.length > 0)
      return LayerSortConstants.LAYER_PRIORITY[LayerType.GROUP];
    return LayerSortConstants.LAYER_PRIORITY[LayerType.NORMAL];
  },

  /**
   * 比较两个图层的排序优先级
   * @param {Object} layerA 图层A
   * @param {Object} layerB 图层B
   * @returns {number} 比较结果
   */
  compareLayerPriority(layerA, layerB) {
    const weightA = this.getLayerSortWeight(layerA);
    const weightB = this.getLayerSortWeight(layerB);
    return weightB - weightA; // 权重高的排在前面（画布上层）
  },
};

/**
 * 图层排序混入方法 - 用于在 LayerManager 中使用
 */
export const LayerSortMixin = {
  /**
   * 初始化图层排序工具
   */
  initLayerSort() {
    this.layerSort = new LayerSort(this.canvas, this.layers);
  },

  /**
   * 重新排列画布对象
   */
  rearrangeCanvasObjects() {
    if (this.layerSort) {
      // 检查是否需要异步处理
      const objectsCount = this.canvas?.getObjects()?.length || 0;
      const layersCount = this.layers?.value?.length || 0;

      if (LayerSortUtils.shouldUseAsyncProcessing(objectsCount, layersCount)) {
        return this.layerSort.rearrangeObjectsAsync();
      } else {
        this.layerSort.rearrangeObjects();
        return Promise.resolve();
      }
    }
  },

  /**
   * 排序图层
   */
  sortLayersWithTool() {
    if (this.layerSort) {
      this.layers.value = this.layerSort.sortLayers();
      return this.layerSort.rearrangeObjects();
    }
  },

  /**
   * 智能排序图层
   */
  smartSortLayers(targetLayerIds = null) {
    if (this.layerSort) {
      return this.layerSort.smartSort(targetLayerIds);
    }
    return false;
  },

  /**
   * 优化图层结构
   */
  optimizeLayerStructure() {
    if (this.layerSort) {
      return this.layerSort.optimizeLayerStructure();
    }
    return { removedEmptyLayers: 0, mergedLayers: 0, reorderedLayers: 0 };
  },
};
