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);
  }
}

/**
 * @async
 * @function checkImageOutsideGrid
 * @description 【核心业务方法】检测图片是否超出打印网格边界，并判断超出部分是否存在有效像素（非透明）
 * 应用场景：印刷/打印场景，校验图片是否超出安全网格，避免裁切丢失内容
 * @returns {Object} 检测结果
 * @property {boolean} isImageBiggerThanGrid - 图片显示尺寸是否大于网格尺寸
 * @property {boolean} hasOutsideValidPixel - 超出网格部分是否存在有效像素（非透明）
 */
async function checkImageOutsideGrid() {
  try {
    // ===================== 第一步：获取DOM元素与页面几何尺寸 =====================
    // 获取打印安全网格容器（id=line）
    const lineDom = document.getElementById("line");
    if (!lineDom) {
      console.log("未找到网格元素（id=line）");
      return {
        isImageBiggerThanGrid: false,
        hasOutsideValidPixel: false,
      };
    }

    // 获取网格元素的页面绝对坐标和尺寸
    const lineRect = lineDom.getBoundingClientRect();
    // 格式化网格边界信息：左、上、右、下、宽、高
    const grid = {
      left: lineRect.left,
      top: lineRect.top,
      right: lineRect.right,
      bottom: lineRect.bottom,
      width: lineRect.width,
      height: lineRect.height,
    };

    // 网格无尺寸，直接返回默认结果
    if (grid.width === 0 || grid.height === 0) {
      return {
        isImageBiggerThanGrid: false,
        hasOutsideValidPixel: false,
      };
    }

    // 获取图片展示容器（id=imgBox）
    const imgDom = document.getElementById("imgBox");
    if (!imgDom) {
      console.log("图片未加载完成或未找到imgBox元素");
      return {
        isImageBiggerThanGrid: false,
        hasOutsideValidPixel: false,
      };
    }

    // 等待图片完全加载完成，保证尺寸获取准确
    await new Promise((resolve) => {
      if (imgDom.complete) resolve();
      else imgDom.onload = resolve;
    });

    // 获取图片在页面上的显示坐标、尺寸
    const imgRect = imgDom.getBoundingClientRect();
    // 获取图片原始分辨率（真实像素尺寸）
    const naturalWidth = imgDom.naturalWidth;
    const naturalHeight = imgDom.naturalHeight;

    // 图片无原始尺寸，直接返回默认结果
    if (naturalWidth === 0 || naturalHeight === 0) {
      console.log("图片原始尺寸为0");
      return {
        isImageBiggerThanGrid: false,
        hasOutsideValidPixel: false,
      };
    }

    // 格式化图片完整信息：显示位置、显示尺寸、原始尺寸
    const imgDisplayInfo = {
      left: imgRect.left,
      top: imgRect.top,
      width: imgRect.width,
      height: imgRect.height,
      naturalWidth,
      naturalHeight,
    };

    // ===================== 【判断1】图片显示尺寸是否大于打印网格 =====================
    const isImageBiggerThanGrid =
      imgDisplayInfo.width > grid.width || imgDisplayInfo.height > grid.height;

    // 图片尺寸≤网格，无需进行像素越界检测，直接返回
    if (!isImageBiggerThanGrid) {
      console.log("图片尺寸小于/等于网格，无需检测越界");
      return {
        isImageBiggerThanGrid: false,
        hasOutsideValidPixel: false,
      };
    }

    // ===================== 第二步：处理图片路径，使用Sharp读取原始像素数据 =====================
    let imgSource = imgDom.src;
    // 兼容处理本地file://协议的图片路径（Electron环境专用）
    if (imgSource.startsWith("file://")) {
      console.log(111);
      // 解析本地文件路径
      imgSource = new URL(imgSource).pathname;
      // Windows系统路径修正（去除开头多余的斜杠）
      if (process.platform === "win32") {
        imgSource = imgSource.slice(1);
      }
      // 解码URI编码字符
      imgSource = decodeURIComponent(imgSource);
    }
    console.log("imgSource", imgSource);

    // 使用Sharp库加载图片
    const sharpImg = sharp(imgSource);
    // 获取图片元信息（宽高、通道数、格式等）
    const imgMetadata = await sharpImg.metadata();
    // 将图片转为原始像素数据（Buffer），方便逐像素检测
    const { data: pixels } = await sharpImg
      .raw()
      .toBuffer({ resolveWithObject: true });

    // ===================== 第三步：坐标映射 + 逐像素检测越界有效像素 =====================
    // 计算缩放比例：图片显示尺寸 / 原始尺寸（页面像素 → 原始像素映射）
    const scaleX = imgDisplayInfo.width / naturalWidth;
    const scaleY = imgDisplayInfo.height / naturalHeight;

    // 标记：是否检测到超出网格的有效像素
    let hasOutsideValidPixel = false;
    // 透明度阈值：Alpha值＞1 视为有效像素（非透明）
    const alphaThreshold = 1;
    // 图片原始宽高
    const imgNaturalWidth = imgMetadata.width;
    const imgNaturalHeight = imgMetadata.height;
    // 判断图片是否包含透明通道（PNG为4通道，JPG为3通道）
    const hasAlpha = imgMetadata.channels === 4;

    // 双层循环：遍历图片所有原始像素
    for (let y = 0; y < imgNaturalHeight; y++) {
      // 已检测到有效像素，直接终止循环，提升性能
      if (hasOutsideValidPixel) break;
      for (let x = 0; x < imgNaturalWidth; x++) {
        // 计算当前原始像素 → 页面上的显示坐标
        const imgDisplayX = parseFloat(
          (imgDisplayInfo.left + x * scaleX).toFixed(2),
        );
        const imgDisplayY = parseFloat(
          (imgDisplayInfo.top + y * scaleY).toFixed(2),
        );

        // 坐标异常，跳过当前像素
        if (isNaN(imgDisplayX) || isNaN(imgDisplayY)) continue;

        // 判断当前像素是否【超出打印网格边界】
        const isOutside =
          imgDisplayX < grid.left ||
          imgDisplayX > grid.right ||
          imgDisplayY < grid.top ||
          imgDisplayY > grid.bottom;

        // 仅处理【超出网格】的像素
        if (isOutside) {
          // 计算当前像素在原始Buffer数据中的索引位置
          const pixelIndex = (y * imgNaturalWidth + x) * imgMetadata.channels;

          // 🔥 核心：判断超出部分是否为【有效像素】（非透明）
          let isValidPixel = false;
          if (hasAlpha) {
            // 图片有透明通道（PNG）：读取Alpha值，判断是否为非透明
            const alpha = pixels[pixelIndex + 3];
            isValidPixel = alpha > alphaThreshold;
          } else {
            // 图片无透明通道（JPG）：所有超出像素都视为有效像素
            isValidPixel = true;
          }

          // 检测到有效越界像素，标记并终止循环
          if (isValidPixel) {
            hasOutsideValidPixel = true;
            console.log(`✅ 检测到超出有效像素（坐标${x},${y}）`);
            break;
          }
        }
      }
    }

    console.log("检测结果：", hasOutsideValidPixel ? "超出网格" : "正常");

    // ===================== 第四步：返回最终检测结果 =====================
    return {
      isImageBiggerThanGrid, // 图片是否大于网格
      hasOutsideValidPixel, // 超出部分是否有真实有效像素
    };
  } catch (error) {
    // 异常捕获：检测失败时，打印错误并返回默认结果，保证程序不崩溃
    console.error("检测失败：", error);
    return {
      isImageBiggerThanGrid: false,
      hasOutsideValidPixel: false,
    };
  }
}

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