/**
 * 基础命令类
 * 所有命令都应该继承这个类
 */
export class Command {
  constructor(options = {}) {
    this.name = options.name || "未命名命令";
    this.description = options.description || "";
    this.undoable = options.undoable !== false; // 默认可撤销
    this.timestamp = Date.now();
  }

  /**
   * 执行命令
   * @returns {*} 执行结果，可以是Promise
   */
  execute() {
    throw new Error("子类必须实现execute方法");
  }

  /**
   * 撤销命令
   * @returns {*} 撤销结果，可以是Promise
   */
  undo() {
    if (!this.undoable) {
      throw new Error("此命令不支持撤销");
    }
    throw new Error("可撤销命令必须实现undo方法");
  }

  /**
   * 获取命令信息
   */
  getInfo() {
    return {
      name: this.name,
      description: this.description,
      undoable: this.undoable,
      timestamp: this.timestamp,
    };
  }
}

/**
 * 复合命令类
 * 用于批量执行多个命令，替代事务系统
 */
export class CompositeCommand extends Command {
  constructor(commands = [], options = {}) {
    super({
      name: options.name || "复合命令",
      description: options.description || "批量执行多个命令",
      ...options,
    });

    this.commands = Array.isArray(commands) ? commands : [];
    this.executedCommands = []; // 记录已执行的命令，用于撤销
    this.isExecuting = false;
  }

  /**
   * 添加子命令
   */
  addCommand(command) {
    if (!command || typeof command.execute !== "function") {
      throw new Error("无效的命令对象");
    }
    this.commands.push(command);
    return this;
  }

  /**
   * 批量添加子命令
   */
  addCommands(commands) {
    if (Array.isArray(commands)) {
      commands.forEach((cmd) => this.addCommand(cmd));
    }
    return this;
  }

  /**
   * 执行所有子命令（串行执行）
   */
  async execute() {
    if (this.isExecuting) {
      throw new Error("复合命令正在执行中");
    }

    this.isExecuting = true;
    this.executedCommands = [];

    try {
      const results = [];

      // 串行执行所有子命令
      for (const command of this.commands) {
        try {
          console.log(`📦 复合命令执行子命令: ${command.constructor.name}`);

          const result = command.execute();

          // 如果是异步命令，等待完成
          const finalResult = this._isPromise(result) ? await result : result;

          results.push(finalResult);
          this.executedCommands.push(command);

          console.log(`✅ 子命令执行成功: ${command.constructor.name}`);
        } catch (error) {
          console.error(`❌ 子命令执行失败: ${command.constructor.name}`, error);

          // 执行失败时，撤销已执行的命令
          await this._rollbackExecutedCommands();
          throw new Error(`复合命令执行失败：${error.message}`);
        }
      }

      this.isExecuting = false;
      console.log(`✅ 复合命令执行完成，共执行 ${results.length} 个子命令`);
      return results;
    } catch (error) {
      this.isExecuting = false;
      throw error;
    }
  }

  /**
   * 撤销所有已执行的子命令（逆序撤销）
   */
  async undo() {
    if (this.isExecuting) {
      throw new Error("复合命令正在执行中，无法撤销");
    }

    if (this.executedCommands.length === 0) {
      console.warn("没有已执行的子命令需要撤销");
      return true;
    }

    console.log(`↩️ 开始撤销复合命令，共 ${this.executedCommands.length} 个子命令`);

    try {
      // 逆序撤销已执行的命令
      const commands = [...this.executedCommands].reverse();
      const results = [];

      for (const command of commands) {
        if (typeof command.undo === "function") {
          try {
            console.log(`↩️ 撤销子命令: ${command.constructor.name}`);

            const result = command.undo();

            // 如果是异步撤销，等待完成
            const finalResult = this._isPromise(result) ? await result : result;

            results.push(finalResult);
            console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
          } catch (error) {
            console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error);
            // 撤销失败不中断整个撤销过程，但要记录错误
          }
        } else {
          console.warn(`⚠️ 子命令不支持撤销: ${command.constructor.name}`);
        }
      }

      this.executedCommands = [];
      console.log(`✅ 复合命令撤销完成`);
      return results;
    } catch (error) {
      console.error("❌ 复合命令撤销过程中发生错误:", error);
      throw error;
    }
  }

  /**
   * 回滚已执行的命令（内部使用）
   * @private
   */
  async _rollbackExecutedCommands() {
    console.log(`🔄 开始回滚已执行的 ${this.executedCommands.length} 个子命令`);

    const commands = [...this.executedCommands].reverse();

    for (const command of commands) {
      if (typeof command.undo === "function") {
        try {
          console.log(`🔄 回滚子命令: ${command.constructor.name}`);
          const result = command.undo();
          if (this._isPromise(result)) {
            await result;
          }
          console.log(`✅ 子命令回滚成功: ${command.constructor.name}`);
        } catch (error) {
          console.error(`❌ 子命令回滚失败: ${command.constructor.name}`, error);
          // 回滚失败不中断整个回滚过程
        }
      }
    }

    this.executedCommands = [];
    console.log(`✅ 回滚完成`);
  }

  /**
   * 检查返回值是否为Promise
   * @private
   */
  _isPromise(value) {
    return (
      value &&
      typeof value === "object" &&
      typeof value.then === "function" &&
      typeof value.catch === "function"
    );
  }

  /**
   * 获取复合命令信息
   */
  getInfo() {
    return {
      ...super.getInfo(),
      commandCount: this.commands.length,
      executedCount: this.executedCommands.length,
      isExecuting: this.isExecuting,
      subCommands: this.commands.map((cmd) => (cmd.getInfo ? cmd.getInfo() : cmd.constructor.name)),
    };
  }
}

/**
 * 函数命令包装器
 * 将普通函数包装为命令对象
 */
export class FunctionCommand extends Command {
  constructor(executeFn, undoFn = null, options = {}) {
    super({
      name: options.name || "函数命令",
      undoable: typeof undoFn === "function",
      ...options,
    });

    if (typeof executeFn !== "function") {
      throw new Error("执行函数不能为空");
    }

    this.executeFn = executeFn;
    this.undoFn = undoFn;
    this.executeResult = null; // 保存执行结果用于撤销
  }

  async execute() {
    const result = this.executeFn();
    this.executeResult = this._isPromise(result) ? await result : result;
    return this.executeResult;
  }

  async undo() {
    if (!this.undoFn) {
      throw new Error("此函数命令不支持撤销");
    }

    const result = this.undoFn(this.executeResult);
    return this._isPromise(result) ? await result : result;
  }

  /**
   * 检查返回值是否为Promise
   * @private
   */
  _isPromise(value) {
    return (
      value &&
      typeof value === "object" &&
      typeof value.then === "function" &&
      typeof value.catch === "function"
    );
  }
}
