import { exec } from "child_process";

var fs = require("fs");
const https = require("https");
const http = require("http");
var path = require("path");
var request = require("request");
var uuid = require("uuid");
const compressing = require("compressing");
const { PassThrough } = require("stream");
const {
  getVersion,

  getDesktopDevice
} = require("@/server/utils/store");

//获取当前驱动版本
function getCurrentVersion() {
  const version = getVersion();
  return version;
}
//获取当前设备类型
function getCurrentDesktopDevice() {
  const version = getDesktopDevice();
  return version;
}

function zip(from, to) {
  return new Promise((resolve, reject) => {
    let dirName = path.join(to, uuid.v4());
    // console.log(dirName);
    if (!fs.existsSync(dirName)) {
      fs.mkdirSync(dirName);
    }
    let arr = [];
    compressing.zip
      .uncompress(from, dirName, { zipFileNameEncoding: "gbk" })
      .then(() => {
        console.log("success");
        let data = fs.readdirSync(dirName);
        for (let i = 0; i < data.length; i++) {
          let fileName = uuid.v4() + ".png";
          let el = data[i];
          let file_path = path.join(dirName, el);
          console.log(file_path, to);
          fs.renameSync(file_path, path.join(to, fileName));
          arr.push({
            fileName: fileName,
            designId: data[i].split("_GCPS")[0],
            productionFile: path.join(to, fileName)
          });
        }

        fs.unlinkSync(from); // 删除压缩包
        fs.rmdirSync(dirName); // 删除目录文件
        // console.log(arr);
        resolve(arr);
      })
      .catch(err => {
        console.log(err);
        reject("压缩包解压失败");
      });
  });
}

export const downloadImage = (list, isForcedProduction) => {
  return new Promise(async (resolve, reject) => {
    try {
      const desktopDevice = getCurrentDesktopDevice();
      const version = desktopDevice == 3 ? "huiLiCaiImg" : getCurrentVersion();
      console.log("version", version);

      const dirPath = path.join(process.cwd(), `./${version}/Input/`);
      // 创建目录（如果不存在）
      if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath, { recursive: true });
      }

      // 过滤出有效的下载项
      const downloadItems = list.filter(
        item => item.url && item.url.includes("http")
      );

      // 如果没有需要下载的项，直接返回
      if (downloadItems.length === 0) {
        return resolve(list);
      }
      // 并行处理所有下载
      const downloadPromises = downloadItems.map(item => {
        return new Promise(async itemResolve => {
          // 创建分流
          const passThrough = new PassThrough();
          try {
            const archiveExtensions = [
              ".zip",
              ".gzip",
              ".tar",
              ".taz",
              ".rar",
              ".7z",
              ".gz",
              ".bz2"
            ];
            const isArchive = archiveExtensions.some(ext =>
              item.url.toLowerCase().includes(ext)
            );
            console.log("item.url", item.url);

            const fileName = isArchive
              ? item.url.split("/").pop()
              : `${uuid.v4()}.png`;

            const filePath = path.join(dirPath, fileName);

            // 使用流下载文件
            const writeStream = fs.createWriteStream(filePath);

            const requestStream = request(item.url);

            // 添加超时处理
            requestStream.on("response", response => {
              response.setTimeout(30000, () => {
                requestStream.abort();
                console.error(`下载超时: ${item.url}`);
                itemResolve();
              });
            });

            // 使用管道连接请求流和写入流
            requestStream.pipe(passThrough);
            passThrough.pipe(writeStream);

            // 等待下载完成
            await new Promise(resolveStream => {
              writeStream.on("finish", resolveStream);
              writeStream.on("error", err => {
                console.error(`下载失败: ${item.url}`, err);
                resolveStream();
              });
            });
            if (isArchive) {
              // 处理压缩文件
              item.list = await zip(filePath, dirPath);
              console.log("list111111111", item.list);
              if (Object.keys(isForcedProduction).length > 0) {
                item.list = item.list.map(el => {
                  if (el.designId.includes("A")) {
                    el.isForcedProduction = isForcedProduction.processDesignA;
                  } else if (el.designId.includes("B")) {
                    el.isForcedProduction = isForcedProduction.processDesignB;
                  }
                  return { ...el };
                });
              }
              console.log("list222222222", item.list);
            } else {
              // 处理普通图片文件
              if (!item.list) item.list = [];
              const originalName = item.url.split("/").pop();
              if (
                isForcedProduction.processDesignA ||
                isForcedProduction.processDesignB
              ) {
                item.list.push({
                  fileName,
                  productionFile: filePath,
                  designId: originalName.split("_GCPS")[0],
                  isForcedProduction: originalName
                    .split("_GCPS")[0]
                    .includes("A")
                    ? isForcedProduction.processDesignA || false
                    : isForcedProduction.processDesignB || false
                });
              } else {
                item.list.push({
                  fileName,
                  productionFile: filePath,
                  designId: originalName.split("_GCPS")[0]
                });
              }
            }
          } catch (error) {
            console.error(`处理失败: ${item.url}`, error);
          } finally {
            itemResolve();
          }
        });
      });

      // 等待所有下载完成
      await Promise.all(downloadPromises);
      resolve(list);
    } catch (err) {
      console.error("下载整体失败", err);
      reject(err);
    }
  });
};

export function downloadOtherImage(list) {
  return new Promise((resolve, reject) => {
    try {
      const desktopDevice = getCurrentDesktopDevice();
      const version = desktopDevice == 3 ? "huiLiCaiImg" : getCurrentVersion();
      console.log("version", version);
      const currentDate = new Date();

      // 将 UTC 时间转换为中国时间 (UTC + 8小时)
      const chinaTimeOffset = 8 * 60 * 60 * 1000; // 8小时，单位是毫秒
      const chinaTime = new Date(currentDate.getTime() + chinaTimeOffset);

      // 将当前中国时间格式化为ISO字符串
      let isoString = chinaTime.toISOString();
      // console.log("Original China Time ISO String:", isoString); // 检查格式

      // 替换掉时间中的 ':' 字符
      const folderName =
        isoString.split("T")[0] +
        "_" +
        isoString
          .split("T")[1]
          .replace(/:/g, "-")
          .split(".")[0];
      let otherTypePath = path.join(
        process.cwd(),
        `./${version}/Input/${folderName}`
      );
      if (!fs.existsSync(otherTypePath)) {
        fs.mkdirSync(otherTypePath);
      }

      let count = 0;
      for (let i = 0; i < list.length; i++) {
        if (list[i].url && list[i].url.includes("http")) {
          let fileName = "";
          let type = 2;
          let flag =
            [
              ".zip",
              ".gzip",
              ".tar",
              ".taz",
              ".rar",
              ".7z",
              ".gz",
              ".bz2"
            ].filter(el => list[i].url.toLowerCase().includes(el)).length > 0;
          if (flag) {
            fileName = list[i].url.split("/")[
              list[i].url.split("/").length - 1
            ];
            type = 1;
          } else {
            fileName = uuid.v4() + ".png";
            type = 2;
          }
          let otherP = path.join(otherTypePath, fileName); // 保存到新文件夹
          let otherstream = fs.createWriteStream(otherP);
          request(list[i].url)
            .pipe(otherstream)
            .on("close", async function() {
              if (type === 1) {
                list[i].list = await zip(otherP, otherTypePath);
                if (count === list.length - 1) {
                  resolve(list);
                }
              } else {
                if (!list[i].list) list[i].list = [];
                const filename = list[i].url.split("/")[
                  list[i].url.split("/").length - 1
                ];
                list[i].list.push({
                  fileName,
                  productionFile: otherP,
                  designId: filename.split("_GCPS")[0]
                });
              }
              if (count === list.length - 1) {
                // console.log(list);
                resolve(list);
              }
              count++;
            });
        }
      }
    } catch (err) {
      console.log(err);
      reject(err);
    }
  });
}

// 传递素材给前端
export const sendImg = (filename = "sample.png") => {
  const desktopDevice = getCurrentDesktopDevice();
  const version = desktopDevice == 3 ? "huiLiCaiImg" : getCurrentVersion();
  console.log("version", version);
  let filePath = path.join(process.cwd(), `./${version}/Input/` + filename);
  if (!fs.existsSync(filePath)) {
    return false;
  }
  let data = fs.readFileSync(filePath);
  data = Buffer.from(data).toString("base64");
  return "data:" + "png" + ";base64," + data;
};

export const toSend = body => {
  const desktopDevice = getCurrentDesktopDevice();
  const version = desktopDevice == 3 ? "huiLiCaiImg" : getCurrentVersion();
  console.log("version", version);

  return new Promise((resolve, reject) => {
    exec(
      body.cmd,
      { cwd: path.join(process.cwd(), version), shell: true },
      err => {
        console.log("err", err);
        if (!err) {
          exec(
            body.print_cmd,
            { cwd: path.join(process.cwd(), version), shell: true },
            err2 => {
              console.log(err2);
              if (!err2) {
                // 成功后删除 素材图，xml，output文件
                // fs.unlinkSync(path.join(process.cwd(), 'print/Input/' + body.fileName))
                fs.unlinkSync(
                  path.join(
                    process.cwd(),
                    `${version}/Profile/` +
                      body.fileName.replace(".png", "") +
                      ".xml"
                  )
                );
                fs.unlinkSync(
                  path.join(
                    process.cwd(),
                    `${version}/Output/` +
                      body.fileName.replace(".png", "") +
                      ".arxp"
                  )
                );
                resolve("操作成功");
              } else {
                const errorDetails = `打印命令失败: ${err2.message}`;
                return reject(`打印机错误: ${errorDetails}`);
              }
            }
          );
        } else {
          // const errorCode = err.code || "UNKNOWN_ERROR";
          // const errorDetails = [
          //   `生成命令失败: ${body.cmd}`,
          //   `错误代码: ${errorCode}`,
          //   `错误信息: ${err.message}`,
          //   `标准错误输出: ${stderr}`,
          // ].join("\n");
          const errorDetails = "未匹配到对应版本的驱动，请检查驱动";
          return reject(errorDetails);
        }
      }
    );
  });
};

export const writeProfileXml = b => {
  // console.log(b);
  const desktopDevice = getCurrentDesktopDevice();
  const version = desktopDevice == 3 ? "huiLiCaiImg" : getCurrentVersion();
  console.log("version", version);
  try {
    let p = path.join(process.cwd(), `./${version}/Profile/${b.byInk}.xml`);
    console.log("writeProfileXml", p);

    let file = fs.readFileSync(p, { encoding: "utf8" });
    file = file.replace(
      /<uiCopies>(.*)<\/uiCopies>/i,
      `<uiCopies>${b.printNum}</uiCopies>`
    );
    file = file.replace(
      /<byPlatenSize>(.*)<\/byPlatenSize>/i,
      `<byPlatenSize>${b.byPlatenSize}</byPlatenSize>`
    );
    file = file.replace(
      /<bEcoMode>(.*)<\/bEcoMode>/i,
      `<bEcoMode>${b.bEcoMode}</bEcoMode>`
    );
    file = file.replace(
      /<bMaterialBlack>(.*)<\/bMaterialBlack>/i,
      `<bMaterialBlack>${b.bMaterialBlack}</bMaterialBlack>`
    );
    file = file.replace(
      /<byHighlight>(.*)<\/byHighlight>/i,
      `<byHighlight>${b.byHighlight}</byHighlight>`
    );
    file = file.replace(
      /<byMask>(.*)<\/byMask>/i,
      `<byMask>${b.byMask}</byMask>`
    );
    file = file.replace(
      /<bTransColor>(.*)<\/bTransColor>/i,
      `<bTransColor>${b.bTransColor}</bTransColor>`
    );
    file = file.replace(
      /<bPause>(.*)<\/bPause>/i,
      `<bPause>${b.bPause}</bPause>`
    );
    file = file.replace(
      /<bDivide>(.*)<\/bDivide>/i,
      `<bDivide>${b.bDivide}</bDivide>`
    );
    file = file.replace(
      /<byChoke>(.*)<\/byChoke>/i,
      `<byChoke>${b.byChoke}</byChoke>`
    );
    file = file.replace(/<byInk>(.*)<\/byInk>/i, `<byInk>${b.byInk}</byInk>`);
    file = file.replace(
      /<bFastMode>(.*)<\/bFastMode>/i,
      `<bFastMode>${b.bFastMode}</bFastMode>`
    );
    file = file.replace(
      /<byResolution>(.*)<\/byResolution>/i,
      `<byResolution>${1}</byResolution>`
    );
    file = file.replace(
      /<byInkVolume>(.*)<\/byInkVolume>/i,
      `<byInkVolume>${b.byInkVolume}</byInkVolume>`
    );
    file = file.replace(
      /<byDoublePrint>(.*)<\/byDoublePrint>/i,
      `<byDoublePrint>${b.byDoublePrint}</byDoublePrint>`
    );
    file = file.replace(
      /<bMultiple>(.*)<\/bMultiple>/i,
      `<bMultiple>${b.bMultiple}</bMultiple>`
    );
    file = file.replace(
      /<bySaturation>(.*)<\/bySaturation>/i,
      `<bySaturation>${b.bySaturation}</bySaturation>`
    );
    file = file.replace(
      /<byBrightness>(.*)<\/byBrightness>/i,
      `<byBrightness>${b.byBrightness}</byBrightness>`
    );
    file = file.replace(
      /<byContrast>(.*)<\/byContrast>/i,
      `<byContrast>${b.byContrast}</byContrast>`
    );
    file = file.replace(
      /<iCyanBalance>(.*)<\/iCyanBalance>/i,
      `<iCyanBalance>${b.iCyanBalance}</iCyanBalance>`
    );
    file = file.replace(
      /<iMagentaBalance>(.*)<\/iMagentaBalance>/i,
      `<iMagentaBalance>${b.iMagentaBalance}</iMagentaBalance>`
    );
    file = file.replace(
      /<iYellowBalance>(.*)<\/iYellowBalance>/i,
      `<iYellowBalance>${b.iYellowBalance}</iYellowBalance>`
    );
    file = file.replace(
      /<iBlackBalance>(.*)<\/iBlackBalance>/i,
      `<iBlackBalance>${b.iBlackBalance}</iBlackBalance>`
    );
    file = file.replace(
      /<bUniPrint>(.*)<\/bUniPrint>/i,
      `<bUniPrint>${b.bUniPrint}</bUniPrint>`
    );
    file = file.replace(
      /<bySubInk>(.*)<\/bySubInk>/i,
      `<bySubInk>${b.bySubInk}</bySubInk>`
    );
    fs.writeFileSync(
      path.join(
        process.cwd(),
        `./${version}/Profile/${b.fileName.replace(".png", "")}.xml`
      ),
      file
    );
  } catch (err) {
    console.log(404, err);
  }
};

/**
 * 复制单个图片文件到目标文件夹（已知图片完整路径）
 * @param {string} sourceImagePath - 源图片的完整绝对路径
 * @param {string} targetDir - 目标文件夹路径（只传文件夹，不用传文件名）
 * @returns {Promise<void>}
 */

const fsPromises = fs.promises; // 明确获取 promises 异步 API

export async function copySingleImage(sourceImagePath, targetDir) {
  try {
    // 步骤1：路径规范化（修正潜在的分隔符/隐形字符问题）
    const normalizedSourcePath = path.resolve(sourceImagePath);
    const normalizedTargetDir = path.resolve(targetDir);
    // 步骤2：校验源文件是否为有效图片文件
    let fileStat;
    try {
      fileStat = await fsPromises.stat(normalizedSourcePath);
    } catch (err) {
      throw new Error(
        `获取源文件状态失败：${err.message}（错误码：${err.code}）`
      );
    }

    // 2.1 校验是否为文件（非文件夹）
    if (!fileStat.isFile()) {
      throw new Error(`源路径不是有效文件，是文件夹：${normalizedSourcePath}`);
    }
    // 2.2 校验是否为图片格式（可选，过滤非图片文件）
    const validImageExts = [".jpg", ".jpeg", ".png", ".gif", ".bmp"];
    const fileExt = path.extname(normalizedSourcePath).toLowerCase();
    if (!validImageExts.includes(fileExt)) {
      throw new Error(
        `源文件不是有效图片格式，后缀为：${fileExt}（支持格式：${validImageExts.join(
          ", "
        )}）`
      );
    }
    // 步骤3：获取文件名 + 拼接目标图片完整路径
    const imageFileName = path.basename(normalizedSourcePath);
    const targetImagePath = path.join(normalizedTargetDir, imageFileName);
    // console.log(`拼接目标文件路径：${targetImagePath}`);

    // 步骤4：创建目标文件夹（递归创建，已存在则不报错）
    try {
      await fsPromises.mkdir(normalizedTargetDir, { recursive: true });
      // console.log(`目标文件夹创建成功（已存在则跳过）：${normalizedTargetDir}`);
    } catch (err) {
      throw new Error(
        `创建目标文件夹失败：${err.message}（错误码：${err.code}）`
      );
    }

    // 步骤5：复制图片文件（核心操作）
    try {
      await fsPromises.copyFile(normalizedSourcePath, targetImagePath);
      console.log(`✅ 图片复制成功！`);
    } catch (err) {
      throw new Error(
        `复制文件操作失败：${err.message}（错误码：${err.code}）`
      );
    }
  } catch (err) {
    console.error("❌ 单个图片复制失败：", err.message);
    throw err;
  }
}

/**
 * 创建批次目录：基础路径/批次号：xxx/三个素材子目录
 * @param {string} basePath 父目录基础路径
 * @param {string} batchNo 批次编号
 */
export function createBatchFolder(basePath, batchNo) {
  try {
    // 拼接外层批次文件夹名称
    const batchDirName = `批次号：${batchNo}`;
    const batchPath = path.join(basePath, batchDirName);

    // 固定子文件夹列表
    const subDirList = ["原素材", "自动排版素材", "手动排版素材"];

    // 1. 判断批次目录是否已存在
    if (fs.existsSync(batchPath)) {
      return { data: batchPath, message: "success" };
    }

    // 2. 创建外层批次目录，recursive自动补全上级目录
    fs.mkdirSync(batchPath, { recursive: true });

    // 3. 批量创建内部三个子目录，存在自动跳过
    subDirList.forEach(subName => {
      const subPath = path.join(batchPath, subName);
      fs.mkdirSync(subPath, { recursive: true });
    });

    // 目录为本次新建
    return { data: batchPath, message: "success" };
  } catch (error) {
    return { message: error.message };
  }
}

export async function createBatchList(basePath, batchNoList) {
  const fs = require("fs").promises;
  const path = require("path");
  const subFolders = ["原素材", "自动排版素材", "手动排版素材"];

  let successCount = 0;
  let skipCount = 0;
  for (const batchNo of batchNoList) {
    const str = `批次号：${batchNo}`;

    const batchPath = path.join(basePath, str);

    try {
      // 已存在就跳过
      try {
        await fs.access(batchPath);
        skipCount++;
        continue;
      } catch {
        // 不存在，继续创建
      }

      // 创建批次文件夹
      await fs.mkdir(batchPath, { recursive: true });

      // 创建三个子文件夹
      await Promise.all(
        subFolders.map(name =>
          fs.mkdir(path.join(batchPath, name), { recursive: true })
        )
      );

      successCount++;
    } catch (e) {
      console.error(`批次 ${batchNo} 创建失败:`, e);
    }
  }
  console.error(`创建完成：成功 ${successCount} 个，跳过 ${skipCount} 个`);
  return true;
}

/**
 * 格式化当前时间为 YYYY-MM-DD HH-mm-ss
 * @returns {string}
 */
function formatTime() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  const hour = String(now.getHours()).padStart(2, "0");
  const minute = String(now.getMinutes()).padStart(2, "0");
  const second = String(now.getSeconds()).padStart(2, "0");
  return `${year}-${month}-${day}_${hour}.${minute}.${second}`;
}
/**
 * 下载文件（图片/zip）到指定目录，zip格式自动解压
 * @param {string} fileUrl - 文件链接（支持png/jpg/zip等）
 * @param {string} targetDir - 目标文件夹绝对路径
 * @param {object} options - 可选配置
 * @param {boolean} options.deleteZipAfterUnzip - 解压后是否删除原zip文件，默认false
 * @param {boolean} options.unzipToSubdir - zip是否解压到同名子文件夹，默认false（直接散列到目标目录）
 * @returns {Promise<{success: boolean, type: string, filePath: string, fileName: string, unzipDir?: string}>}
 */
export function downloadDTFFiles(fileUrl, targetDir, options = {}) {
  const { deleteZipAfterUnzip = true, unzipToSubdir = false } = options;
  console.log("downloadDTFFiles---------", fileUrl, targetDir);

  return new Promise((resolve, reject) => {
    try {
      // 1. 解析URL，判断协议
      const urlObj = new URL(fileUrl);
      const requestLib = urlObj.protocol === "https:" ? https : http;

      // 2. 递归创建目标目录
      if (!fs.existsSync(targetDir)) {
        fs.mkdirSync(targetDir, { recursive: true });
      }

      // 3. 提取文件名（去除参数/哈希，无后缀默认补.jpg）
      let cleanPath = urlObj.pathname;
      try {
        // 先解码URL编码字符，还原 / 和 \
        cleanPath = decodeURIComponent(urlObj.pathname);
      } catch (e) {
        // 解码失败则使用原始路径兜底
        cleanPath = urlObj.pathname;
      }
      // 统一所有反斜杠为正斜杠，兼容Windows路径格式
      cleanPath = cleanPath.replace(/\\/g, "/");
      // 提取最后一段：纯文件名（含后缀）
      const originalFileName = path.basename(cleanPath);

      // 最终命名：时间 + 原文件名，兜底空文件名
      const fileName = originalFileName
        ? `${formatTime()} ${originalFileName}`
        : `${formatTime()}.png`;
      const savePath = path.join(targetDir, fileName);

      // 4. 发起网络请求
      const request = requestLib.get(fileUrl, response => {
        // 处理301/302重定向
        if ([301, 302, 307, 308].includes(response.statusCode)) {
          const redirectUrl = response.headers.location;
          const finalRedirectUrl = redirectUrl.startsWith("http")
            ? redirectUrl
            : new URL(redirectUrl, fileUrl).href;

          downloadDTFFiles(finalRedirectUrl, targetDir, options)
            .then(resolve)
            .catch(reject);
          response.resume();
          return;
        }

        if (response.statusCode !== 200) {
          reject(new Error(`下载失败，HTTP状态码：${response.statusCode}`));
          return;
        }

        // 5. 流式写入文件
        const writeStream = fs.createWriteStream(savePath);
        response.pipe(writeStream);

        // 写入完成：判断格式，zip自动解压
        writeStream.on("finish", () => {
          writeStream.close(async () => {
            const fileExt = path.extname(fileName).toLowerCase();

            // 非zip文件：直接返回
            if (fileExt !== ".zip") {
              resolve({
                success: true,
                type: "image",
                filePath: savePath,
                fileName: fileName
              });
              return;
            }

            // zip文件：执行解压
            try {
              // 解压目标目录：直接解压到目标目录 / 或解压到同名子文件夹
              let unzipTargetDir = targetDir;
              if (unzipToSubdir) {
                const dirName = path.basename(fileName, ".zip");
                unzipTargetDir = path.join(targetDir, dirName);
                if (!fs.existsSync(unzipTargetDir)) {
                  fs.mkdirSync(unzipTargetDir, { recursive: true });
                }
              }

              // 执行解压
              await compressing.zip.uncompress(savePath, unzipTargetDir);

              // 可选：解压完成后删除原zip文件
              if (deleteZipAfterUnzip) {
                fs.unlinkSync(savePath);
              }

              resolve({
                success: true,
                type: "zip",
                filePath: savePath,
                fileName: fileName,
                unzipDir: unzipTargetDir
              });
            } catch (unzipErr) {
              reject(new Error(`ZIP解压失败：${unzipErr.message}`));
            }
          });
        });

        // 写入异常：删除残留文件
        writeStream.on("error", err => {
          if (fs.existsSync(savePath)) {
            fs.unlink(savePath, () => {});
          }
          reject(new Error(`文件写入失败：${err.message}`));
        });
      });

      // 网络请求异常
      request.on("error", err => {
        reject(new Error(`网络请求失败：${err.message}`));
      });

      // 超时控制
      request.setTimeout(15000, () => {
        request.destroy();
        reject(new Error("下载超时，请检查网络或链接有效性"));
      });
    } catch (err) {
      reject(new Error(`参数校验失败：${err.message}`));
    }
  });
}
