const fs = require("fs");
const path = require("path");
const sharp = require("sharp");

/**
 * 裁切单个图片的透明白边
 * @param {string} inputPath - 输入图片路径
 * @param {string} outputPath - 输出图片路径
 * @param {Object} options - 配置选项
 * @param {number} options.threshold - 透明度阈值，0-255之间，默认为10
 * @returns {Promise<Object>} - 返回处理结果
 */
async function cropImageTransparentEdges(inputPath, outputPath, options = {}) {
  const threshold = options.threshold || 10;

  // 确保输出目录存在
  const outputDir = path.dirname(outputPath);
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  try {
    // 读取图片信息
    const metadata = await sharp(inputPath).metadata();

    // 提取图片的透明通道信息
    const { data, info } = await sharp(inputPath)
      .raw()
      .ensureAlpha()
      .toBuffer({ resolveWithObject: true });

    const { width, height, channels } = info;
    // console.log("width", width);
    // console.log("height", height);

    // 找到图片的边界
    let topmost = height;
    let bottommost = 0;
    let leftmost = width;
    let rightmost = 0;

    for (let y = 0; y < height; y++) {
      for (let x = 0; x < width; x++) {
        const alphaIdx = (y * width + x) * channels + channels - 1;
        const alpha = data[alphaIdx];

        // 如果像素不是透明的（根据阈值）
        if (alpha > threshold) {
          topmost = Math.min(topmost, y);
          bottommost = Math.max(bottommost, y);
          leftmost = Math.min(leftmost, x);
          rightmost = Math.max(rightmost, x);
        }
      }
    }

    // 如果图片全透明，保持原样
    if (topmost > bottommost || leftmost > rightmost) {
      await sharp(inputPath).toFile(outputPath);
      return {
        status: "unchanged",
        reason: "全透明图片",
        inputPath,
        outputPath,
      };
    }

    // 计算裁切区域
    const cropWidth = rightmost - leftmost + 1;
    const cropHeight = bottommost - topmost + 1;
    // console.log("metadatawidth", metadata.width);
    // console.log("metadataheight", metadata.height);
    // 裁切并保存图片
    await sharp(inputPath)
      .extract({
        left: leftmost,
        top: topmost,
        width: cropWidth,
        height: cropHeight,
      })
      .toFile(outputPath);

    return {
      status: "cropped",
      inputPath,
      outputPath,
      originalSize: { width: metadata.width, height: metadata.height },
      newSize: { width: cropWidth, height: cropHeight },
    };
  } catch (error) {
    return {
      status: "error",
      inputPath,
      outputPath,
      error: error.message,
    };
  }
}

/**
 * 裁切图片目录中的所有图片的透明白边
 * @param {string} inputDir - 输入图片目录
 * @param {string} outputDir - 输出图片目录
 * @param {Object} options - 配置选项
 * @param {number} options.threshold - 透明度阈值，0-255之间，默认为10
 * @returns {Promise<Array>} - 返回处理结果数组
 */
async function cropTransparentEdges(inputDir, outputDir, options = {}) {
  // 确保输出目录存在
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  // 获取输入目录中的所有图片文件
  const files = fs.readdirSync(inputDir).filter((file) => {
    const ext = path.extname(file).toLowerCase();
    return [".png", ".jpg", ".jpeg", ".webp"].includes(ext);
  });

  const results = [];

  // 处理每个图片
  for (const file of files) {
    const inputPath = path.join(inputDir, file);
    const outputPath = path.join(outputDir, file);

    const result = await cropImage(inputPath, outputPath, options);
    results.push({ file, ...result });
  }

  return results;
}

/**
 * 处理图片并输出结果
 * @param {string} inputPath - 输入图片路径或目录
 * @param {string} outputPath - 输出图片路径或目录
 * @param {Object} options - 配置选项
 * @param {number} options.threshold - 透明度阈值，0-255之间，默认为10
 */
async function processImages(inputPath, outputPath, options = {}) {
  console.log(`开始处理图片，从 ${inputPath} 到 ${outputPath}`);

  try {
    let results = [];

    // 检查输入是文件还是目录
    const inputStat = fs.statSync(inputPath);

    if (inputStat.isDirectory()) {
      // 如果输入是目录，检查输出是否有扩展名
      const outputExt = path.extname(outputPath);
      if (outputExt) {
        throw new Error("如果输入是目录，输出也必须是目录");
      }

      // 处理目录下的所有图片
      results = await cropTransparentEdges(inputPath, outputPath, options);
    } else {
      // 处理单个图片
      const result = await cropImage(inputPath, outputPath, options);
      results = [{ file: path.basename(inputPath), ...result }];
    }

    console.log("处理完成!");
    console.log(
      `成功处理: ${
        results.filter((r) => r.status === "cropped").length
      } 张图片`,
    );
    console.log(
      `保持不变: ${
        results.filter((r) => r.status === "unchanged").length
      } 张图片`,
    );
    console.log(
      `处理失败: ${results.filter((r) => r.status === "error").length} 张图片`,
    );
    fs.unlinkSync(inputPath);
    return results;
  } catch (error) {
    console.error("处理图片过程中出错:", error);
    throw error;
  }
}

/**
 * 裁切方法优化
 */
async function cropImage(inputPath, outputPath, options = {}) {
  const {
    threshold = 10, // 透明度阈值
    stripHeight = 64, // 流式模式条带高度
    maxDimension = 2500, // 小图/大图分界点
    padding = 0, // 裁剪后留白
    debug = true, // 调试模式
    forceStreamMode = false, // 强制使用流式模式
  } = options;

  // 确保输出目录存在
  const outputDir = path.dirname(outputPath);
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  try {
    // 获取图像元数据
    const metadata = await sharp(inputPath).metadata();
    const { width, height } = metadata;
    const channels = metadata.channels || 4;
    const alphaIndex = channels - 1;

    // 根据尺寸选择处理模式
    const useStreamMode =
      forceStreamMode || width > maxDimension || height > maxDimension;

    let bounds = {
      top: height,
      bottom: 0,
      left: width,
      right: 0,
      foundPixels: false,
    };

    if (debug) {
      console.log(`处理图像: ${width}x${height}`);
      console.log(`模式: ${useStreamMode ? "流式处理" : "快速处理"}`);
    }

    if (useStreamMode) {
      // 流式安全模式（处理大图）
      await processInStreamMode(inputPath, bounds, {
        width,
        height,
        channels,
        alphaIndex,
        threshold,
        stripHeight,
        debug,
      });
    } else {
      // 快速模式（处理小图）
      await processInFastMode(inputPath, bounds, {
        width,
        height,
        channels,
        alphaIndex,
        threshold,
      });
    }

    // 检查是否找到有效像素
    if (!bounds.foundPixels) {
      // 全透明图像直接复制
      await fs.promises.copyFile(inputPath, outputPath);

      return {
        status: "unchanged",
        reason: "全透明图片",
        originalSize: { width, height },
      };
    }

    // 应用边界留白
    applyPadding(bounds, padding, width, height);

    // 计算裁剪区域
    const cropWidth = Math.min(
      width - bounds.left,
      bounds.right - bounds.left + 1,
    );
    const cropHeight = Math.min(
      height - bounds.top,
      bounds.bottom - bounds.top + 1,
    );

    if (cropWidth <= 0 || cropHeight <= 0) {
      throw new Error(`无效的裁剪尺寸: ${cropWidth}x${cropHeight}`);
    }

    // 如果裁剪区域和原图一样则跳过
    // if (cropWidth === width && cropHeight === height) {
    //   await fs.promises.copyFile(inputPath, outputPath);

    //   return {
    //     status: "unchanged",
    //     reason: "裁剪尺寸与原图相同",
    //     originalSize: { width, height },
    //   };
    // }

    // 执行裁剪
    await sharp(inputPath)
      .extract({
        left: bounds.left,
        top: bounds.top,
        width: cropWidth,
        height: cropHeight,
      })
      .toFile(outputPath);

    return {
      status: "cropped",
      outputPath,
      originalSize: { width, height },
      newSize: { width: cropWidth, height: cropHeight },
      cropArea: {
        x: bounds.left,
        y: bounds.top,
        width: cropWidth,
        height: cropHeight,
      },
    };
  } catch (error) {
    return {
      status: "error",
      error: error.message,
      stack: error.stack,
    };
  }
}

async function processInStreamMode(inputPath, bounds, options) {
  const {
    width,
    height,
    channels,
    alphaIndex,
    threshold,
    stripHeight,
    debug,
  } = options;

  // 垂直分条带处理（从0到height）
  for (let y = 0; y < height; y += stripHeight) {
    const currentStripHeight = Math.min(stripHeight, height - y);

    // 读取当前条带
    const stripData = await sharp(inputPath)
      .extract({
        left: 0,
        top: y,
        width,
        height: currentStripHeight,
      })
      .raw()
      .toBuffer();

    // 处理当前条带内的像素
    for (let row = 0; row < currentStripHeight; row++) {
      const rowStartIdx = row * width * channels;
      let rowHasPixel = false;

      // 扫描当前行寻找像素
      for (let x = 0; x < width; x++) {
        const idx = rowStartIdx + x * channels + alphaIndex;
        if (stripData[idx] > threshold) {
          rowHasPixel = true;
          const absY = y + row;

          // 更新垂直边界
          if (absY < bounds.top) bounds.top = absY;
          if (absY > bounds.bottom) bounds.bottom = absY;

          // 更新水平边界
          if (x < bounds.left) bounds.left = x;
          if (x > bounds.right) bounds.right = x;
        }
      }

      // 标记找到像素
      if (rowHasPixel) bounds.foundPixels = true;
    }

    // 调试信息
    if (debug && y % (stripHeight * 10) === 0) {
      console.log(
        `流式处理进度: ${y}/${height} (${Math.round((y / height) * 100)}%)`,
      );
    }
  }
}

// 快速模式（高效处理小图）
async function processInFastMode(inputPath, bounds, options) {
  const { width, height, channels, alphaIndex, threshold } = options;

  // 一次性读取整个图像
  const imageBuffer = await sharp(inputPath)
    .raw()
    .toBuffer();

  // 遍历整张图像
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const idx = (y * width + x) * channels + alphaIndex;
      if (imageBuffer[idx] > threshold) {
        bounds.foundPixels = true;

        // 更新所有边界
        if (y < bounds.top) bounds.top = y;
        if (y > bounds.bottom) bounds.bottom = y;
        if (x < bounds.left) bounds.left = x;
        if (x > bounds.right) bounds.right = x;
      }
    }
  }
}

// ================= 辅助函数 =================

// 应用边界留白
function applyPadding(bounds, padding, imgWidth, imgHeight) {
  if (padding > 0) {
    bounds.top = Math.max(0, bounds.top - padding);
    bounds.bottom = Math.min(imgHeight - 1, bounds.bottom + padding);
    bounds.left = Math.max(0, bounds.left - padding);
    bounds.right = Math.min(imgWidth - 1, bounds.right + padding);
  }
}

// 分区边界检测实现

module.exports = {
  cropTransparentEdges,
  cropImageTransparentEdges,
  processImages,
  cropImage,
};
