/**
 * 增强版液化管理器
 * 整合WebGL和CPU实现，智能选择最佳渲染方式
 */
import { LiquifyWebGLManager } from "./LiquifyWebGLManager";
import { LiquifyCPUManager } from "./LiquifyCPUManager";
import { findLayerRecursively, LayerType } from "../../utils/layerHelper";
import i18n from "@/lang/index.ts";
const {t} = i18n.global;

export class EnhancedLiquifyManager {
  /**
   * 创建增强版液化管理器
   * @param {Object} options 配置选项
   */
  constructor(options = {}) {
    this.config = {
      // 性能阈值：图像超过此尺寸会尝试使用WebGL
      webglSizeThreshold: options.webglSizeThreshold || 1000 * 1000, // 默认100万像素
      // 是否强制使用CPU模式
      forceCPU: options.forceCPU || false,
      // 是否强制使用WebGL模式
      forceWebGL: options.forceWebGL || false,
      // 网格大小
      gridSize: options.gridSize || 8,
      // 最大变形强度
      maxStrength: options.maxStrength || 200,
      // 平滑迭代次数
      smoothingIterations: options.smoothingIterations || 1,
      // 网格弹性因子
      relaxFactor: options.relaxFactor || 0.05,
      // WebGL网格精度
      meshResolution: options.meshResolution || 64,
    };

    // 性能监控
    this.performance = {
      lastOperationTime: 0,
      renderTimes: [], // 最近的渲染时间记录
      isPerformanceIssue: false, // 是否存在性能问题
      operationCount: 0, // 操作计数
    };

    // 初始化标志
    this.initialized = false;

    // 当前参数
    this.params = {
      size: 50, // 工具尺寸
      pressure: 0.5, // 压力大小 (0-1)
      distortion: 0, // 失真程度 (0-1)
      power: 0.5, // 动力/强度 (0-1)
    };

    // 液化工具模式
    this.modes = {
      PUSH: "push",
      CLOCKWISE: "clockwise",
      COUNTERCLOCKWISE: "counterclockwise",
      PINCH: "pinch",
      EXPAND: "expand",
      CRYSTAL: "crystal",
      EDGE: "edge",
      RECONSTRUCT: "reconstruct",
    };

    // 当前模式
    this.currentMode = this.modes.PUSH;

    // 图像数据和目标对象
    this.originalImageData = null;
    this.currentImageData = null;
    this.targetObject = null;
    this.targetLayerId = null;

    // 创建渲染器实例
    this.webglRenderer = null;
    this.cpuRenderer = null;

    // 当前激活的渲染器
    this.activeRenderer = null;
    this.renderMode = "unknown"; // 'webgl', 'cpu', 'unknown'

    // 画布和管理器引用
    this.canvas = options.canvas || null;
    this.layerManager = options.layerManager || null;

    // 渲染器状态
    this.isWebGLAvailable = LiquifyWebGLManager.isSupported();
  }

  /**
   * 初始化液化管理器
   * @param {Object} options 配置选项
   * @returns {Boolean} 是否初始化成功
   */
  initialize(options = {}) {
    if (options.canvas) this.canvas = options.canvas;
    if (options.layerManager) this.layerManager = options.layerManager;

    if (!this.canvas || !this.layerManager) {
      console.error("液化管理器初始化失败：缺少canvas或layerManager");
      return false;
    }

    // 记录初始化时间，用于性能监控
    this.performance.lastInitTime = Date.now();

    // 创建CPU渲染器 (始终创建作为备选)
    this.cpuRenderer = new LiquifyCPUManager({
      gridSize: this.config.gridSize,
      maxStrength: this.config.maxStrength,
      smoothingIterations: this.config.smoothingIterations,
      relaxFactor: this.config.relaxFactor,
    });

    // 检查是否应创建WebGL渲染器
    if (this.isWebGLAvailable && !this.config.forceCPU) {
      this.webglRenderer = new LiquifyWebGLManager({
        gridSize: this.config.gridSize,
        maxStrength: this.config.maxStrength,
        meshResolution: this.config.meshResolution,
      });
    }

    this.initialized = true;
    return true;
  }

  /**
   * 为液化操作准备图像
   * @param {Object|String} target 目标对象或图层ID
   * @returns {Promise<Object>} 准备结果
   */
  async prepareForLiquify(target) {
    if (!this.initialized) {
      throw new Error("液化管理器未初始化");
    }

    let targetObject, targetLayerId;

    // 处理传入的是图层ID的情况
    if (typeof target === "string") {
      targetLayerId = target;
      const { layer } = findLayerRecursively(
        this.layerManager.layers?.value ?? this.layerManager.layers,
        targetLayerId
      );

      // 检查图层是否存在和是否有对象
      let hasObjects = false;
      if (layer) {
        if (layer.type === "background" && layer.fabricObject) {
          hasObjects = true;
          targetObject = layer.fabricObject;
        } else if (layer.fabricObjects && layer.fabricObjects.length > 0) {
          hasObjects = true;
          targetObject = layer.fabricObjects[0];
        }
      }

      if (!hasObjects) {
        throw new Error("目标图层为空或不存在");
      }
    } else if (typeof target === "object") {
      // 传入的是对象
      targetObject = target;
      const { layer } = findLayerRecursively(
        this.layerManager.layers?.value ?? this.layerManager.layers,
        targetObject.layerId
      );
      if (layer) {
        targetLayerId = layer.id;
      } else {
        throw new Error("无法找到目标对象所属图层");
      }
    } else {
      throw new Error("无效的目标参数");
    }

    // 检查是否为图像对象
    if (!targetObject || targetObject.type !== "image") {
      throw new Error("目标对象不是图像，无法进行液化操作");
    }

    // 保存目标对象引用
    this.targetObject = targetObject;
    this.targetLayerId = targetLayerId;

    // 获取图像数据
    const imageData = await this._getImageData(targetObject);
    if (!imageData) {
      throw new Error("无法获取图像数据");
    }

    // 保存原始图像数据
    this.originalImageData = imageData;
    this.currentImageData = this._cloneImageData(imageData);

    // 检查图像大小，选择适合的渲染器
    await this._selectRenderer(imageData);

    // 预热选定的渲染器
    await this._warmupRenderer(imageData);

    return {
      targetObject: this.targetObject,
      targetLayerId: this.targetLayerId,
      imageData: this.currentImageData,
      originalImageData: this.originalImageData,
      renderMode: this.renderMode,
    };
  }

  /**
   * 根据图像大小和设备性能选择渲染器
   * @param {ImageData} imageData 图像数据
   * @private
   */
  async _selectRenderer(imageData) {
    // 计算图像大小
    const pixelCount = imageData.width * imageData.height;

    console.log(
      `液化选择渲染器: 图像大小=${pixelCount}像素, WebGL可用=${this.isWebGLAvailable}`
    );

    // 默认使用CPU渲染器
    this.activeRenderer = this.cpuRenderer;
    this.renderMode = "cpu";

    // 如果配置强制使用WebGL
    if (this.config.forceWebGL && this.isWebGLAvailable && this.webglRenderer) {
      console.log("液化功能: 强制使用WebGL渲染模式");
      this.activeRenderer = this.webglRenderer;
      this.renderMode = "webgl";
      return;
    }

    // 如果配置强制使用CPU
    if (this.config.forceCPU) {
      console.log("液化功能: 强制使用CPU渲染模式");
      return;
    }

    // 根据图像大小和WebGL可用性决定
    if (
      pixelCount > this.config.webglSizeThreshold / 2 && // 降低阈值，让更多尺寸的图像使用WebGL
      this.isWebGLAvailable &&
      this.webglRenderer
    ) {
      // 切换到WebGL渲染器
      console.log("液化功能: 自动选择WebGL渲染模式(基于图像尺寸)");
      this.activeRenderer = this.webglRenderer;
      this.renderMode = "webgl";
    } else {
      console.log(
        `液化功能: 使用CPU渲染模式${
          !this.isWebGLAvailable ? " (WebGL不可用)" : ""
        }`
      );
    }
  }

  /**
   * 预热渲染器
   * @param {ImageData} imageData 图像数据
   * @private
   */
  async _warmupRenderer(imageData) {
    // 创建图像元素
    const img = document.createElement("img");

    // 将ImageData转换为URL
    const canvas = document.createElement("canvas");
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext("2d");
    ctx.putImageData(imageData, 0, 0);

    // 使用Promise等待图像加载
    await new Promise((resolve, reject) => {
      img.onload = resolve;
      img.onerror = reject;
      img.src = canvas.toDataURL();
    });

    // 初始化当前渲染器
    if (this.activeRenderer) {
      if (this.renderMode === "webgl") {
        this.activeRenderer.initialize(img);
      } else {
        this.activeRenderer.initialize(imageData);
      }
    }
  }

  /**
   * 设置液化模式
   * @param {String} mode 模式名称
   */
  setMode(mode) {
    if (Object.values(this.modes).includes(mode)) {
      this.currentMode = mode;

      // 同步更新当前渲染器
      if (this.activeRenderer) {
        this.activeRenderer.setMode(mode);
      }

      return true;
    }
    return false;
  }

  /**
   * 设置液化参数
   * @param {String} param 参数名称
   * @param {Number} value 参数值
   */
  setParam(param, value) {
    if (param in this.params) {
      this.params[param] = value;

      // 同步更新当前渲染器 - 关键修复：确保参数正确传递
      if (
        this.activeRenderer &&
        typeof this.activeRenderer.setParam === "function"
      ) {
        console.log(`EnhancedLiquifyManager 设置参数: ${param}=${value}`);
        this.activeRenderer.setParam(param, value);
      } else {
        console.warn(
          `EnhancedLiquifyManager: 无法设置参数 ${param}，渲染器未就绪`
        );
      }

      return true;
    }

    console.warn(`EnhancedLiquifyManager: 无效参数 ${param}`);
    return false;
  }

  /**
   * 批量设置参数
   * @param {Object} params 参数对象
   */
  setParams(params) {
    console.log("EnhancedLiquifyManager 批量设置参数:", params);

    if (params && typeof params === "object") {
      Object.entries(params).forEach(([key, value]) => {
        this.setParam(key, value);
      });
    }
  }

  /**
   * 获取当前参数
   * @returns {Object} 当前参数对象
   */
  getParams() {
    return { ...this.params };
  }

  /**
   * 重置参数为默认值
   */
  resetParams() {
    this.params = {
      size: 50,
      pressure: 0.5,
      distortion: 0,
      power: 0.5,
    };

    // 同步更新当前渲染器
    if (this.activeRenderer) {
      this.activeRenderer.resetParams();
    }
  }

  /**
   * 开始液化操作（记录初始点）
   * @param {Number} x 初始X坐标
   * @param {Number} y 初始Y坐标
   */
  startLiquifyOperation(x, y) {
    if (
      this.activeRenderer &&
      typeof this.activeRenderer.startDeformation === "function"
    ) {
      this.activeRenderer.startDeformation(x, y);
    }
    console.log(
      `开始液化操作，渲染模式=${this.renderMode}, 初始点: (${x}, ${y})`
    );
  }

  /**
   * 结束液化操作
   */
  endLiquifyOperation() {
    if (
      this.activeRenderer &&
      typeof this.activeRenderer.endDeformation === "function"
    ) {
      this.activeRenderer.endDeformation();
    }
    console.log(`结束液化操作，渲染模式=${this.renderMode}`);
  }

  /**
   * 应用液化变形
   * @param {Object} target 目标对象
   * @param {String} mode 液化模式
   * @param {Object} params 液化参数
   * @param {Number} x 操作中心点X坐标 (图像像素坐标)
   * @param {Number} y 操作中心点Y坐标 (图像像素坐标)
   * @returns {Promise<ImageData>} 处理后的图像数据
   */
  async applyLiquify(target, mode, params, x, y) {
    // 性能追踪开始
    const startTime = performance.now();

    // 如果首次调用，先准备环境
    if (!this.targetObject || this.targetObject !== target) {
      await this.prepareForLiquify(target);
    }

    // 更新模式和参数
    if (mode) this.setMode(mode);
    if (params) {
      for (const [key, value] of Object.entries(params)) {
        this.setParam(key, value);
      }
    }

    // 验证坐标是否在图像范围内
    if (!this.originalImageData) {
      console.error("缺少原始图像数据");
      return null;
    }

    const imageWidth = this.originalImageData.width;
    const imageHeight = this.originalImageData.height;

    // 坐标边界检查
    if (x < 0 || x >= imageWidth || y < 0 || y >= imageHeight) {
      console.warn(
        `液化坐标超出图像范围: (${x}, ${y}), 图像尺寸: ${imageWidth}x${imageHeight}`
      );
      return null;
    }

    console.log(
      `应用液化变形: 模式=${mode}, 图像坐标=(${x}, ${y}), 图像尺寸=${imageWidth}x${imageHeight}`
    );

    // 检查并应用变形
    if (this.activeRenderer && typeof x === "number" && typeof y === "number") {
      // 应用变形
      let result;

      if (this.renderMode === "webgl") {
        // WebGL渲染器：传入图像像素坐标
        result = this.activeRenderer.applyDeformation(x, y);
      } else {
        // CPU渲染器：传入图像像素坐标
        result = this.activeRenderer.applyDeformation(x, y);
      }

      // 更新当前图像数据
      if (result) {
        this.currentImageData = result;
      }

      // 性能追踪结束
      const endTime = performance.now();
      this._trackPerformance(endTime - startTime);

      return result;
    }

    console.error("无法应用液化变形：渲染器未初始化或坐标无效");
    return null;
  }

  /**
   * 追踪性能数据
   * @param {Number} time 操作耗时(毫秒)
   * @private
   */
  _trackPerformance(time) {
    this.performance.lastOperationTime = time;
    this.performance.operationCount++;

    // 维护最近10次操作的耗时记录
    this.performance.renderTimes.push(time);
    if (this.performance.renderTimes.length > 10) {
      this.performance.renderTimes.shift();
    }

    // 计算平均耗时
    const avgTime =
      this.performance.renderTimes.reduce((sum, t) => sum + t, 0) /
      this.performance.renderTimes.length;

    // 检测性能问题
    this.performance.isPerformanceIssue = avgTime > 100; // 如果平均耗时超过100毫秒

    // 输出性能信息（调试用）
    if (this.performance.operationCount % 10 === 0) {
      console.log(
        `液化性能数据: 模式=${this.renderMode}, 平均耗时=${avgTime.toFixed(
          2
        )}ms, 图像尺寸=${this.originalImageData?.width}x${
          this.originalImageData?.height
        }`
      );
    }

    // 如果使用WebGL但性能差，可以考虑切换到优化的CPU实现
    if (
      this.renderMode === "webgl" &&
      this.performance.isPerformanceIssue &&
      this.performance.operationCount > 5
    ) {
      console.warn("WebGL液化性能不佳，考虑切换到CPU模式");
      // 注意：这里不自动切换，因为可能会导致中途渲染结果不一致
    }
  }
  setRealtimeUpdater(realtimeUpdater) {
    this.realtimeUpdater = realtimeUpdater;
  }
  /**
   * 重置液化操作
   * @returns {ImageData} 重置后的图像数据
   */
  reset() {
    if (!this.activeRenderer) return null;

    // 使用当前渲染器重置
    const result = this.activeRenderer.reset();

    // 更新当前图像数据
    if (result) {
      this.currentImageData = result;
    }

    return result;
  }

  /**
   * 检查图层是否可以液化
   * @param {String} layerId 图层ID
   * @returns {Object} 检查结果
   */
  checkLayerForLiquify(layerId) {
    if (!this.layerManager) {
      return {
        valid: false,
        message: "图层管理器未初始化",
        needsRasterization: false,
        isImage: false,
        isEmpty: true,
        isGroup: false,
      };
    }

    // 获取图层
    // const layer = this.layerManager.getLayerById(layerId);
    const { layer } = findLayerRecursively(
      this.layerManager.layers?.value ?? this.layerManager.layers,
      layerId
    );
    if (!layer) {
      return {
        valid: false,
        message: "图层不存在",
        needsRasterization: false,
        isImage: false,
        isEmpty: true,
        isGroup: false,
      };
    }

    // 检查图层是否为空
    let objectsToCheck = [];
    if (layer.isBackground || layer.type === "background" || layer.isFixed) {
      // 背景图层使用 fabricObject (单数)
      if (layer.fabricObject) {
        objectsToCheck = [layer.fabricObject];
      }
    } else {
      // 普通图层使用 fabricObjects (复数)
      objectsToCheck = layer.fabricObjects || [];
    }

    if (objectsToCheck.length === 0) {
      return {
        valid: false,
        message: t('Canvas.layerEmptyNoLiquidation'),
        needsRasterization: false,
        isImage: false,
        isEmpty: true,
        isGroup: false,
      };
    }

    // 检查是否为单一图像
    const singleObject = objectsToCheck.length === 1;
    const isImage =
      singleObject &&
      (objectsToCheck[0].type === "image" ||
        objectsToCheck[0].type === "rasterized-layer");

    // 检查是否为组
    const isGroup =
      objectsToCheck.some((obj) => obj.type === "group") ||
      layer.type === LayerType.GROUP ||
      layer.children?.length > 0;

    // 如果不是单一图像，需要栅格化
    const needsRasterization = !isImage || isGroup;

    return {
      valid: isImage && !isGroup,
      message: isImage ? "图层可以进行液化操作" : "需要先将图层栅格化",
      needsRasterization: needsRasterization,
      isImage: isImage,
      isEmpty: false,
      isGroup: isGroup,
    };
  }

  /**
   * 获取图像数据
   * @param {Object} fabricObject Fabric图像对象
   * @returns {Promise<ImageData>} 图像数据
   * @private
   */
  async _getImageData(fabricObject) {
    return new Promise((resolve, reject) => {
      try {
        console.log("开始获取图像数据，对象类型:", fabricObject.type);
        console.log("对象属性:", {
          width: fabricObject.width,
          height: fabricObject.height,
          hasElement: !!fabricObject._element,
          hasSrc: !!fabricObject.getSrc,
        });

        // 检查基本属性
        if (!fabricObject.width || !fabricObject.height) {
          reject(new Error("图像对象缺少有效的宽度或高度"));
          return;
        }

        // 创建临时canvas - 使用原始图像尺寸，不考虑fabric对象的缩放
        const tempCanvas = document.createElement("canvas");
        tempCanvas.width = fabricObject.width;
        tempCanvas.height = fabricObject.height;
        const tempCtx = tempCanvas.getContext("2d");

        console.log(
          `创建临时Canvas，尺寸: ${tempCanvas.width}x${tempCanvas.height}`
        );

        // 处理不同的图像源
        if (fabricObject._element) {
          console.log("使用 _element 绘制图像");

          // 检查_element是否有效
          if (
            !fabricObject._element.complete &&
            fabricObject._element.tagName === "IMG"
          ) {
            console.log("图像未加载完成，等待加载...");
            fabricObject._element.onload = () => {
              try {
                tempCtx.drawImage(
                  fabricObject._element,
                  0,
                  0,
                  fabricObject.width,
                  fabricObject.height
                );
                const imageData = tempCtx.getImageData(
                  0,
                  0,
                  tempCanvas.width,
                  tempCanvas.height
                );
                console.log("✅ 图像加载完成后获取数据成功");
                resolve(imageData);
              } catch (error) {
                console.error("图像加载后绘制失败:", error);
                reject(error);
              }
            };
            fabricObject._element.onerror = () => {
              reject(new Error("图像加载失败"));
            };
            return;
          }

          // 直接绘制已加载的图像
          tempCtx.drawImage(
            fabricObject._element,
            0,
            0,
            fabricObject.width,
            fabricObject.height
          );
        } else if (
          fabricObject.getSrc &&
          typeof fabricObject.getSrc === "function"
        ) {
          console.log("使用 getSrc() 方法获取图像源");

          // 通过URL创建图像
          const img = new Image();
          img.crossOrigin = "anonymous"; // 避免跨域问题

          img.onload = () => {
            try {
              console.log(
                `图像加载成功，原始尺寸: ${img.naturalWidth}x${img.naturalHeight}`
              );

              tempCtx.drawImage(
                img,
                0,
                0,
                fabricObject.width,
                fabricObject.height
              );

              const imageData = tempCtx.getImageData(
                0,
                0,
                tempCanvas.width,
                tempCanvas.height
              );

              console.log("✅ 通过URL获取图像数据成功");
              resolve(imageData);
            } catch (error) {
              console.error("绘制图像失败:", error);
              reject(error);
            }
          };

          img.onerror = (error) => {
            console.error("图像加载失败:", error);
            reject(new Error("无法加载图像URL: " + fabricObject.getSrc()));
          };

          const srcUrl = fabricObject.getSrc();
          console.log("加载图像URL:", srcUrl);
          img.src = srcUrl;
          return;
        } else if (fabricObject.src) {
          console.log("使用 src 属性获取图像源");

          // 通过src属性创建图像
          const img = new Image();
          img.crossOrigin = "anonymous";

          img.onload = () => {
            try {
              tempCtx.drawImage(
                img,
                0,
                0,
                fabricObject.width,
                fabricObject.height
              );

              const imageData = tempCtx.getImageData(
                0,
                0,
                tempCanvas.width,
                tempCanvas.height
              );

              console.log("✅ 通过src属性获取图像数据成功");
              resolve(imageData);
            } catch (error) {
              console.error("通过src绘制图像失败:", error);
              reject(error);
            }
          };

          img.onerror = (error) => {
            console.error("通过src加载图像失败:", error);
            reject(new Error("无法加载图像src: " + fabricObject.src));
          };

          console.log("加载图像src:", fabricObject.src);
          img.src = fabricObject.src;
          return;
        } else {
          console.error("无法找到有效的图像源");
          reject(
            new Error("图像对象缺少有效的图像源（_element, getSrc, 或 src）")
          );
          return;
        }

        // 如果走到这里，说明使用了_element直接绘制
        try {
          const imageData = tempCtx.getImageData(
            0,
            0,
            tempCanvas.width,
            tempCanvas.height
          );

          console.log(
            `✅ 获取图像数据成功: 对象尺寸=${fabricObject.width}x${fabricObject.height}, ` +
              `对象缩放=(${fabricObject.scaleX}, ${fabricObject.scaleY}), ` +
              `图像数据尺寸=${imageData.width}x${imageData.height}`
          );

          resolve(imageData);
        } catch (error) {
          console.error("获取ImageData失败:", error);
          reject(new Error("无法从Canvas获取图像数据: " + error.message));
        }
      } catch (error) {
        console.error("_getImageData 执行失败:", error);
        reject(error);
      }
    });
  }

  /**
   * 克隆图像数据
   * @param {ImageData} imageData 原始图像数据
   * @returns {ImageData} 克隆的图像数据
   * @private
   */
  _cloneImageData(imageData) {
    if (!imageData) return null;

    // 使用新的浏览器API直接复制
    if (typeof ImageData.prototype.constructor === "function") {
      try {
        return new ImageData(
          new Uint8ClampedArray(imageData.data),
          imageData.width,
          imageData.height
        );
      } catch (e) {
        console.warn("使用备选方法克隆ImageData");
      }
    }

    // 备选方法
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");

    canvas.width = imageData.width;
    canvas.height = imageData.height;

    ctx.putImageData(imageData, 0, 0);

    return ctx.getImageData(0, 0, imageData.width, imageData.height);
  }

  /**
   * 释放资源
   */
  dispose() {
    // 释放渲染器资源
    if (this.webglRenderer) {
      this.webglRenderer.dispose();
      this.webglRenderer = null;
    }

    if (this.cpuRenderer) {
      this.cpuRenderer.dispose();
      this.cpuRenderer = null;
    }

    // 清除引用
    this.activeRenderer = null;
    this.canvas = null;
    this.layerManager = null;
    this.targetObject = null;
    this.originalImageData = null;
    this.currentImageData = null;
    this.initialized = false;
    this.renderMode = "unknown";
  }

  /**
   * 获取当前状态信息
   * @returns {Object} 状态信息
   */
  getStatus() {
    return {
      initialized: this.initialized,
      renderMode: this.renderMode,
      isWebGLAvailable: this.isWebGLAvailable,
      currentMode: this.currentMode,
      params: { ...this.params },
      performance: { ...this.performance },
      imageSize: this.originalImageData
        ? `${this.originalImageData.width}x${this.originalImageData.height}`
        : "N/A",
    };
  }
}
