import QRCodeStyling from "qr-code-styling";
import { SvgProcessor } from "../utils/images/svg/SvgProcessor";
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
import { JSDOM } from "jsdom";
import sharp from "sharp";
import { Buffer } from "buffer";

interface GenerateOptions {
  format: "png" | "svg";
  label?: string;
  color?: string;
  logoColor?: string;
  width?: number;
  height?: number;
  padding?: number;
}

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export async function generateQRCodeImage(
  uri: string,
  {
    format = "svg",
    label = "Сообщите о проблеме или задайте вопрос",
    color = "#000",
    logoColor = "#000",
    width = 800,
    height = 800,
    padding = 32,
  }: GenerateOptions,
): Promise<Buffer> {
  const optimizeOutput = format === "svg";
  const logoPath = path.resolve(__dirname, "../../assets/logo.svg");
  const logoWithText = new SvgProcessor(
    await fs.readFile(logoPath, "utf8"),
    optimizeOutput,
  )
    .replaceFill(logoColor) // Заменяем цвет fill в лого
    .addLabel("НаСвязи", logoColor, 0.01) // Добавляем лейбл "НаСвязи" в логотип
    // .addPadding(padding) // Добавляем отступы вокруг логотипа
    .toString();

  const qrCode = new QRCodeStyling({
    jsdom: JSDOM, // this is required
    width,
    height,
    data: uri,
    image: `data:image/svg+xml;base64,${Buffer.from(logoWithText, "utf8").toString("base64")}`,
    imageOptions: {
      margin: 20,
      imageSize: 0.45,
    },
    type: "svg",
    backgroundOptions: {
      color: "transparent",
    },
    cornersSquareOptions: {
      type: "extra-rounded",
    },
    cornersDotOptions: {
      type: "dot",
    },
    dotsOptions: {
      color,
      type: "classy-rounded",
    },
  });

  const rawData = await qrCode.getRawData("svg");

  if (!rawData || !(rawData instanceof Buffer)) {
    throw new Error("Не удалось получить данные QR-кода");
  }

  // Преобразуем SVG в строку
  let resultSvg = rawData.toString("utf8");

  resultSvg = new SvgProcessor(resultSvg, optimizeOutput)
    .addLabel(label, color)
    .addPadding(padding)
    .toString();

  if (format === "svg") {
    if (!resultSvg) {
      throw new Error("Ошибка оптимизации SVG");
    }

    // Если формат SVG, возвращаем буфер SVG
    return Buffer.from(resultSvg, "utf8");
  }

  // Если формат PNG, преобразуем resultSvg в PNG через sharp
  return sharp(Buffer.from(resultSvg, "utf8")).toFormat("png").toBuffer();
}
