import { Command, CompositeCommand } from "./Command.js";
import { fabric } from "fabric-with-all";
import { createLayer, LayerType } from "../utils/layerHelper.js";
import { createRasterizedImage } from "../utils/selectionToImage.js";
import { generateId } from "../utils/helper.js";

/**
 * 创建选区命令
 */
export class CreateSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: options.name || "创建选区",
      description: "在画布上创建选区",
      saveState: false,
    });
    this.canvas = options.canvas;
    this.selectionManager = options.selectionManager;
    this.selectionObject = options.selectionObject;
    this.selectionType = options.selectionType || "rectangle";
  }

  async execute() {
    if (!this.canvas || !this.selectionManager || !this.selectionObject) {
      console.error("无法创建选区：参数无效");
      return false;
    }

    // 将选择对象添加到选区管理器
    this.selectionManager.setSelectionObject(this.selectionObject);
    return true;
  }

  async undo() {
    if (!this.selectionManager) return false;
    this.selectionManager.clearSelection();
    return true;
  }
}

/**
 * 反转选区命令
 */
export class InvertSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: "反转选区",
      description: "反转当前选区",
      saveState: false,
    });
    this.canvas = options.canvas;
    this.selectionManager = options.selectionManager;
    this.originalSelection = options.selectionManager
      ? options.selectionManager.getSelectionPath()
      : null;
  }

  async execute() {
    if (!this.canvas || !this.selectionManager) {
      console.error("无法反转选区：参数无效");
      return false;
    }

    // 保存原始选区
    if (!this.originalSelection) {
      this.originalSelection = this.selectionManager.getSelectionPath();
    }

    // 反转选区
    const result = await this.selectionManager.invertSelection();
    return result;
  }

  async undo() {
    if (!this.selectionManager || !this.originalSelection) return false;

    // 恢复原始选区
    this.selectionManager.setSelectionFromPath(this.originalSelection);
    return true;
  }
}

/**
 * 添加到选区命令
 */
export class AddToSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: "添加到选区",
      description: "将新的选区添加到现有选区",
      saveState: false,
    });
    this.canvas = options.canvas;
    this.selectionManager = options.selectionManager;
    this.newSelection = options.newSelection;
    this.originalSelection = options.selectionManager
      ? options.selectionManager.getSelectionPath()
      : null;
  }

  async execute() {
    if (!this.canvas || !this.selectionManager || !this.newSelection) {
      console.error("无法添加到选区：参数无效");
      return false;
    }

    // 保存原始选区
    if (!this.originalSelection) {
      this.originalSelection = this.selectionManager.getSelectionPath();
    }

    // 添加到选区
    const result = await this.selectionManager.addToSelection(this.newSelection);
    return result;
  }

  async undo() {
    if (!this.selectionManager || !this.originalSelection) return false;

    // 恢复原始选区
    this.selectionManager.setSelectionFromPath(this.originalSelection);
    return true;
  }
}

/**
 * 从选区中移除命令
 */
export class RemoveFromSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: "从选区中移除",
      description: "从现有选区中移除指定区域",
      saveState: false,
    });
    this.canvas = options.canvas;
    this.selectionManager = options.selectionManager;
    this.removeSelection = options.removeSelection;
    this.originalSelection = options.selectionManager
      ? options.selectionManager.getSelectionPath()
      : null;
  }

  async execute() {
    if (!this.canvas || !this.selectionManager || !this.removeSelection) {
      console.error("无法从选区中移除：参数无效");
      return false;
    }

    // 保存原始选区
    if (!this.originalSelection) {
      this.originalSelection = this.selectionManager.getSelectionPath();
    }

    // 从选区中移除
    const result = await this.selectionManager.removeFromSelection(this.removeSelection);
    return result;
  }

  async undo() {
    if (!this.selectionManager || !this.originalSelection) return false;

    // 恢复原始选区
    this.selectionManager.setSelectionFromPath(this.originalSelection);
    return true;
  }
}

/**
 * 羽化选区命令
 */
export class FeatherSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: "羽化选区",
      description: "对当前选区应用羽化效果",
      saveState: false,
    });
    this.selectionManager = options.selectionManager;
    this.featherAmount = options.featherAmount || 5;
    this.originalSelection = options.selectionManager
      ? options.selectionManager.getSelectionPath()
      : null;
    this.originalFeatherAmount = options.selectionManager
      ? options.selectionManager.getFeatherAmount()
      : 0;
  }

  async execute() {
    if (!this.selectionManager) {
      console.error("无法羽化选区：参数无效");
      return false;
    }

    // 保存原始选区和羽化值
    if (!this.originalSelection) {
      this.originalSelection = this.selectionManager.getSelectionPath();
      this.originalFeatherAmount = this.selectionManager.getFeatherAmount();
    }

    // 应用羽化
    const result = await this.selectionManager.featherSelection(this.featherAmount);
    return result;
  }

  async undo() {
    if (!this.selectionManager || !this.originalSelection) return false;

    // 恢复原始选区和羽化值
    this.selectionManager.setSelectionFromPath(this.originalSelection);
    this.selectionManager.setFeatherAmount(this.originalFeatherAmount);
    return true;
  }
}

/**
 * 填充选区命令
 */
export class FillSelectionCommand extends Command {
  constructor(options = {}) {
    super({
      name: "填充选区",
      description: "使用指定颜色填充当前选区",
      saveState: false,
    });
    this.canvas = options.canvas;
    this.layerManager = options.layerManager;
    this.selectionManager = options.selectionManager;
    this.color = options.color || "#000000";
    this.targetLayerId = options.targetLayerId;
    this.createdObjectIds = [];
  }

  async execute() {
    if (!this.canvas || !this.layerManager || !this.selectionManager) {
      console.error("无法填充选区：参数无效");
      return false;
    }

    // 获取选区路径
    const selectionPath = this.selectionManager.getSelectionObject();
    if (!selectionPath) {
      console.error("无法填充选区：当前没有选区");
      return false;
    }

    // 确定目标图层
    const layerId = this.targetLayerId || this.layerManager.getActiveLayerId();
    if (!layerId) {
      console.error("无法填充选区：没有活动图层");
      return false;
    }

    // 创建填充对象
    const fillObject = new fabric.Path(selectionPath.path, {
      fill: this.color,
      stroke: null,
      opacity: 1,
      id: `fill_${Date.now()}_${Math.floor(Math.random() * 1000)}`,
      layerId: layerId,
      selectable: false,
    });

    // 应用羽化效果（如果有）
    const featherAmount = this.selectionManager.getFeatherAmount();
    if (featherAmount > 0) {
      fillObject.shadow = new fabric.Shadow({
        color: this.color,
        blur: featherAmount,
        offsetX: 0,
        offsetY: 0,
      });
    }

    // 添加到图层
    this.layerManager.addObjectToLayer(layerId, fillObject);
    this.createdObjectIds.push(fillObject.id);

    // 清空选区
    this.selectionManager.clearSelection();
    return true;
  }

  async undo() {
    if (!this.layerManager || this.createdObjectIds.length === 0) return false;

    // 移除创建的填充对象
    for (const id of this.createdObjectIds) {
      const layerObj = this._findObjectInLayers(id);
      if (layerObj) {
        this.layerManager.removeObjectFromLayer(layerObj.layerId, id);
      }
    }
    return true;
  }

  _findObjectInLayers(objectId) {
    if (!this.layerManager) return null;

    const layers = this.layerManager.layers.value;
    for (const layer of layers) {
      if (layer.fabricObjects) {
        const obj = layer.fabricObjects.find((obj) => obj.id === objectId);
        if (obj) return { object: obj, layerId: layer.id };
      }
    }
    return null;
  }
}

/**
 * 复制选区内容到新图层命令
 */
export class CopySelectionToNewLayerCommand extends CompositeCommand {
  constructor(options = {}) {
    super([], {
      name: "复制选区到新图层",
      description: "将选区中的内容复制到新图层",
    });
    this.canvas = options.canvas;
    this.layerManager = options.layerManager;
    this.selectionManager = options.selectionManager;
    this.sourceLayerId = options.sourceLayerId;
    this.newLayerName = options.newLayerName || "选区复制";
    this.newLayerId = null;
    this.copiedObjectIds = [];
  }

  async execute() {
    if (!this.canvas || !this.layerManager || !this.selectionManager) {
      console.error("无法复制选区：参数无效");
      return false;
    }

    try {
      // 获取选区
      const selectionObject = this.selectionManager.getSelectionObject();
      if (!selectionObject) {
        console.error("无法复制选区：当前没有选区");
        return false;
      }

      // 确定源图层
      const sourceId = this.sourceLayerId || this.layerManager.getActiveLayerId();
      const sourceLayer = this.layerManager.getLayerById(sourceId);
      if (!sourceLayer || !sourceLayer.fabricObjects) {
        console.error("无法复制选区：源图层无效或为空");
        return false;
      }

      // 创建新图层
      this.newLayerId = await this.layerManager.createLayer(this.newLayerName, LayerType.EMPTY);

      // 获取选区内的对象
      const objectsToCopy = sourceLayer.fabricObjects.filter((obj) => {
        return this.selectionManager.isObjectInSelection(obj);
      });

      if (objectsToCopy.length === 0) {
        console.warn("选区内没有对象可复制");
        return true; // 仍然返回成功，因为已创建了新图层
      }

      // 复制对象到新图层
      for (const obj of objectsToCopy) {
        // 克隆对象
        const clonedObj = await this._cloneObject(obj);
        // 设置新的ID和图层ID
        const newId = `copy_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
        clonedObj.id = newId;
        clonedObj.layerId = this.newLayerId;

        // 添加到新图层
        await this.layerManager.addObjectToLayer(this.newLayerId, clonedObj);
        this.copiedObjectIds.push(newId);
      }

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

      // 清空选区
      this.selectionManager.clearSelection();

      return {
        newLayerId: this.newLayerId,
        copiedCount: this.copiedObjectIds.length,
      };
    } catch (error) {
      console.error("复制选区过程中出错:", error);

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

      throw error;
    }
  }

  async _cloneObject(obj) {
    return new Promise((resolve, reject) => {
      if (!obj) {
        reject(new Error("对象无效，无法克隆"));
        return;
      }

      try {
        obj.clone((cloned) => {
          resolve(cloned);
        });
      } catch (error) {
        reject(error);
      }
    });
  }
}
