// 栅格化帮助
import { fabric } from "fabric-with-all";
import { createStaticCanvas } from "./canvasFactory";
/**
 * 创建栅格化图像
 * 使用组对象方式，避免边界计算误差
 * @returns {Promise<fabric.Image>} 栅格化后的图像对象
 * @private
 */
export const createRasterizedImage = async ({
  canvas, // 画布对象   必填
  fabricObjects = [], // 要栅格化的对象列表  -  按顺序  必填
  maskObject = null, // 用于裁剪的对象  -  可选
  trimWhitespace = true, // 是否裁剪空白区域
  trimPadding = 0, // 裁剪边距
  quality = 1.0, // 图像质量
  format = "png", // 图像格式
  scaleFactor = 2, //  高清倍数  - 默认是画布的高清倍数
  isReturenDataURL = false, // 是否返回DataURL而不是fabric.Image对象
  isThumbnail = false, // 是否为缩略图
  preserveOriginalQuality = true, // 是否保持原始质量
  isGroupWithMask = false, // 是否为带遮罩的组图层
} = {}) => {
  try {
    console.log(`📊 开始栅格化 ${fabricObjects.length} 个对象${maskObject ? "（带遮罩）" : ""}`);

    // 确保有对象需要栅格化
    if (fabricObjects.length === 0) {
      console.warn("⚠️ 没有对象需要栅格化，返回空图像");
      return null;
    }

    // 高清倍数
    const currentZoom = canvas.getZoom?.() || 1;
    scaleFactor = Math.max(scaleFactor || canvas?.getRetinaScaling?.(), currentZoom);

    if (isThumbnail) scaleFactor = 0.2; // 缩略图使用较小的高清倍数

    console.log(`高清倍数: ${scaleFactor}, 当前缩放: ${currentZoom}`);

    // 如果有遮罩且保持原始质量，使用高质量的遮罩处理方法
    if (maskObject && preserveOriginalQuality) {
      const rasterizedImage = await createRasterizedImageWithMask({
        canvas,
        objects: fabricObjects,
        maskObject,
        scaleFactor,
        quality,
        format,
        currentZoom,
        isReturenDataURL,
        isGroupWithMask,
      });

      if (!rasterizedImage) {
        console.warn("⚠️ 带遮罩的栅格化图像创建失败，返回空图像");
        return null;
      }

      if (isReturenDataURL) {
        console.log("✅ 带遮罩的栅格化图像创建成功，返回DataURL");
        return rasterizedImage;
      }

      // 设置栅格化图像的属性
      rasterizedImage.set({
        selectable: true,
        evented: true,
        hasControls: true,
        hasBorders: true,
        custom: {
          type: "rasterized",
          rasterizedAt: new Date().toISOString(),
          objectCount: fabricObjects.length,
          originalZoom: currentZoom,
          hasMask: true,
        },
      });

      console.log(`✅ 带遮罩的栅格化图像创建完成`);
      return rasterizedImage;
    }

    // 使用原有的组对象方式创建栅格化图像
    const rasterizedImage = await createRasterizedImageWithGroup({
      canvas,
      objects: fabricObjects,
      scaleFactor,
      maskObject,
      trimWhitespace,
      trimPadding,
      quality,
      format,
      currentZoom,
      isReturenDataURL,
    });

    if (!rasterizedImage) {
      console.warn("⚠️ 栅格化图像创建失败，返回空图像");
      return null;
    }

    if (isReturenDataURL) {
      console.log("✅ 栅格化图像创建成功，返回DataURL");
      return rasterizedImage;
    }

    // 设置栅格化图像的属性
    if (rasterizedImage) {
      rasterizedImage.set({
        selectable: true,
        evented: true,
        hasControls: true,
        hasBorders: true,
        custom: {
          type: "rasterized",
          rasterizedAt: new Date().toISOString(),
          objectCount: fabricObjects.length,
          originalZoom: currentZoom,
        },
      });

      console.log(`✅ 栅格化图像创建完成`);
    }

    return rasterizedImage;
  } catch (error) {
    console.error("创建栅格化图像失败:", error);
    throw new Error(`栅格化失败: ${error.message}`);
  }
};

/**
 * 使用组对象方式创建栅格化图像
 * @param {Object} options 渲染选项
 * @returns {Promise<fabric.Image>} 栅格化后的图像对象
 */
const createRasterizedImageWithGroup = async ({
  canvas,
  objects,
  scaleFactor,
  maskObject,
  trimWhitespace,
  trimPadding,
  quality,
  format,
  currentZoom,
  isReturenDataURL,
}) => {
  try {
    // 创建离屏画布
    const offscreenCanvas = createStaticCanvas();

    // 克隆所有对象
    const clonedObjects = [];
    for (const obj of objects) {
      const clonedObj = await cloneObjectAsync(obj);
      clonedObj.set({
        select: false,
        evented: false,
        hasControls: false,
        clipPath: null, // 确保克隆对象没有clipPath
      });
      clonedObjects.push(clonedObj);
    }

    // 创建组对象
    const group = new fabric.Group(clonedObjects, {
      originX: "left",
      originY: "top",
    });

    // 获取组的绝对边界框
    const groupBounds = group.getBoundingRect(true, true);
    console.log("📏 组边界框:", groupBounds);

    // 设置离屏画布尺寸，使用组的边界大小
    const canvasWidth = Math.ceil(groupBounds.width * scaleFactor);
    const canvasHeight = Math.ceil(groupBounds.height * scaleFactor);

    offscreenCanvas.setDimensions({
      width: canvasWidth,
      height: canvasHeight,
      hasControls: false,
    });

    console.log(`🎨 离屏画布尺寸: ${canvasWidth}x${canvasHeight}, 缩放: ${scaleFactor}`);

    // 调整组的位置，让它位于画布的左上角
    group.set({
      left: 0,
      top: 0,
    });

    // 取消对象激活
    group.set({
      selectable: false, // 禁用组的选择
      evented: false, // 禁用组的事件
    });

    // 将组添加到离屏画布
    offscreenCanvas.add(group);

    // 设置离屏画布的缩放
    offscreenCanvas.setZoom(scaleFactor);

    // 如果有遮罩对象，应用遮罩
    if (maskObject) {
      await applyMaskToCanvas(offscreenCanvas, maskObject, groupBounds);
    }

    // 渲染离屏画布
    offscreenCanvas.renderAll();

    // 生成图像数据
    const dataURL = offscreenCanvas.toDataURL({
      format,
      quality,
      multiplier: 1, // 已经通过画布尺寸处理了高清倍数
    });

    if (isReturenDataURL) {
      // 清理离屏画布
      offscreenCanvas.dispose();
      return dataURL; // 如果需要返回DataURL
    }

    // 清理离屏画布
    offscreenCanvas.dispose();

    // 创建fabric.Image对象
    const fabricImage = await createFabricImageFromDataURL(dataURL);

    // 设置图像的位置和缩放，使其与原始组的位置和大小匹配
    fabricImage.set({
      scaleX: 1 / scaleFactor, // 由于我们生成的图像是高清版本，需要缩放回原始大小
      scaleY: 1 / scaleFactor,
      left: groupBounds.left + groupBounds.width / 2, // 设置为组中心点
      top: groupBounds.top + groupBounds.height / 2, // 设置为组中心点
      originX: "center",
      originY: "center",
    });

    return fabricImage;
  } catch (error) {
    console.error("组对象栅格化失败:", error);
    throw error;
  }
};

/**
 * 使用遮罩创建栅格化图像 - 专门处理带遮罩的组图层
 * 基于遮罩的位置和大小来裁剪内容，确保正确的定位
 * @param {Object} options 渲染选项
 * @returns {Promise<fabric.Image>} 栅格化后的图像对象
 */
const createRasterizedImageWithMask = async ({
  canvas,
  objects,
  maskObject,
  scaleFactor,
  quality,
  format,
  currentZoom,
  isReturenDataURL,
  isGroupWithMask,
}) => {
  try {
    console.log("🎭 使用遮罩创建栅格化图像");

    // 获取遮罩的边界框，这将作为最终图像的边界
    const maskBounds = maskObject.getBoundingRect(true, true);
    console.log("📏 遮罩边界框:", maskBounds);

    // 克隆所有对象，并清除它们的遮罩，避免重复应用
    const clonedObjects = [];
    for (const obj of objects) {
      const clonedObj = await cloneObjectAsync(obj);
      clonedObj.set({
        select: false,
        evented: false,
        hasControls: false,
        clipPath: null, // 清除clipPath，避免重复应用遮罩
      });
      clonedObjects.push(clonedObj);
    }

    // 克隆遮罩对象用于裁剪
    const clonedMask = await cloneObjectAsync(maskObject);
    clonedMask.set({
      select: false,
      evented: false,
      hasControls: false,
      absolutePositioned: false, // 设置为绝对定位
      // fill: "#ffffff", // 遮罩使用白色
      // stroke: "", // 确保没有描边
      // strokeWidth: 0,
    });
    clonedMask.clipPath = null; // 确保克隆的遮罩没有clipPath

    // 创建离屏画布，使用遮罩的边界大小
    const offscreenCanvas = createStaticCanvas();
    const canvasWidth = Math.ceil(maskBounds.width * scaleFactor);
    const canvasHeight = Math.ceil(maskBounds.height * scaleFactor);

    offscreenCanvas.setDimensions({
      width: canvasWidth,
      height: canvasHeight,
    });

    console.log(`🎨 离屏画布尺寸: ${canvasWidth}x${canvasHeight}, 缩放: ${scaleFactor}`);

    // 调整对象位置，相对于遮罩边界重新定位
    clonedObjects.forEach((obj) => {
      obj.set({
        left: (obj.left - maskBounds.left) * scaleFactor,
        top: (obj.top - maskBounds.top) * scaleFactor,
        scaleX: (obj.scaleX || 1) * scaleFactor,
        scaleY: (obj.scaleY || 1) * scaleFactor,
      });
      obj.setCoords();
    });

    // 调整遮罩位置
    clonedMask.set({
      left: 0, // 遮罩从画布左上角开始
      top: 0,
      scaleX: (clonedMask.scaleX || 1) * scaleFactor,
      scaleY: (clonedMask.scaleY || 1) * scaleFactor,
      originX: "left",
      originY: "top",
      absolutePositioned: true, // 设置为绝对定位
    });
    clonedMask.setCoords();

    // 添加所有对象到离屏画布
    clonedObjects.forEach((obj) => {
      offscreenCanvas.add(obj);
    });

    // 使用遮罩作为画布的clipPath来裁剪内容
    offscreenCanvas.clipPath = clonedMask;

    // 渲染离屏画布
    offscreenCanvas.renderAll();

    // 生成图像数据
    const dataURL = offscreenCanvas.toDataURL({
      format,
      quality,
      multiplier: 1, // 已经通过画布尺寸和对象缩放处理了高清倍数
    });

    if (isReturenDataURL) {
      // 清理离屏画布
      offscreenCanvas.dispose();
      return dataURL;
    }

    // 清理离屏画布
    offscreenCanvas.dispose();

    // 创建fabric.Image对象
    const fabricImage = await createFabricImageFromDataURL(dataURL);

    // 设置图像的位置，使其与原始遮罩的位置匹配
    fabricImage.set({
      scaleX: 1 / scaleFactor, // 由于我们生成的图像是高清版本，需要缩放回原始大小
      scaleY: 1 / scaleFactor,
      left: maskBounds.left + maskBounds.width / 2, // 设置为遮罩中心点
      top: maskBounds.top + maskBounds.height / 2, // 设置为遮罩中心点
      originX: "center",
      originY: "center",
    });

    // 确保图像位置正确
    fabricImage.setCoords();

    console.log("✅ 带遮罩的栅格化图像创建完成");
    return fabricImage;
  } catch (error) {
    console.error("带遮罩的栅格化失败:", error);
    throw error;
  }
};

/**
 * 异步克隆fabric对象
 * @param {fabric.Object} obj 要克隆的对象
 * @returns {Promise<fabric.Object>} 克隆的对象
 */
const cloneObjectAsync = (obj) => {
  return new Promise((resolve, reject) => {
    try {
      obj?.clone?.((cloned) => {
        if (cloned) {
          resolve(cloned);
        } else {
          reject(new Error("对象克隆失败"));
        }
      }, {});
    } catch (error) {
      reject(new Error(`克隆对象时发生错误: ${error.message}`));
    }
  });
};

/**
 * 从DataURL创建fabric.Image对象
 * @param {string} dataURL 图像数据URL
 * @returns {Promise<fabric.Image>} fabric图像对象
 */
const createFabricImageFromDataURL = (dataURL) => {
  return new Promise((resolve, reject) => {
    fabric.Image.fromURL(dataURL, (img) => {
      if (img) {
        resolve(img);
      } else {
        reject(new Error("无法从DataURL创建图像"));
      }
    });
  });
};

/**
 * 应用遮罩到画布（如果需要）
 * @param {fabric.Canvas} canvas 目标画布
 * @param {fabric.Object} maskObject 遮罩对象
 * @param {Object} bounds 边界框
 */
const applyMaskToCanvas = async (canvas, maskObject, bounds) => {
  if (!maskObject) {
    console.log("没有遮罩对象，跳过遮罩应用");
    return;
  }

  try {
    console.log("🎭 应用遮罩到画布");

    // 克隆遮罩对象，避免影响原对象
    const clonedMask = await cloneObjectAsync(maskObject);

    // 设置遮罩属性
    clonedMask.set({
      fill: "#ffffff", // 遮罩使用白色
      stroke: "", // 确保没有描边
      strokeWidth: 0,
      selectable: false,
      evented: false,
      absolutePositioned: true, // 设置为绝对定位
    });

    // 调整遮罩位置，相对于画布边界重新定位
    clonedMask.set({
      left: clonedMask.left - bounds.left,
      top: clonedMask.top - bounds.top,
    });

    // 将遮罩设置为画布的clipPath
    canvas.clipPath = clonedMask;

    console.log("✅ 遮罩应用完成");
  } catch (error) {
    console.error("应用遮罩失败:", error);
  }
};

/**
 * 获取对象组的边界框
 * @param {Array} fabricObjects fabric对象数组
 * @returns {Object} 边界框信息
 */
export const getObjectsBounds = (fabricObjects) => {
  if (fabricObjects.length === 0) {
    return null;
  }

  // 创建临时组来获取准确的边界框
  const tempGroup = new fabric.Group([...fabricObjects], {
    originX: "left",
    originY: "top",
  });

  const bounds = tempGroup.getBoundingRect(true, true);

  // 清理临时组
  tempGroup.destroy();

  return bounds;
};
