import fs from "fs";
import path from "path";
import os from "os";
import { execFile } from "child_process";
import { promisify } from "util";

import pkg from "whatsapp-web.js";
import { createSticker } from "wa-sticker-formatter";

import { client } from "../client/whatsappClient.js";
import { botMsg } from "../utils/botMsg.js";
import { emptyFolder } from "../utils/file.js";
import { stickerSessions } from "./index.js";

const { MessageMedia } = pkg;
const execFileAsync = promisify(execFile);

const DOWNLOADS_DIR = path.resolve("downloads");
const FFMPEG = os.platform() === "win32"
  ? ".\\bin\\ffmpeg.exe"
  : "./bin/ffmpeg";

const MAX_STICKER_SIZE = 900 * 1024;
const SESSION_TIMEOUT = 2 * 60 * 1000;
const MAX_MEDIA = 10;

// ───────────────── Helpers ─────────────────

function ensureDownloadsDir() {
  if (!fs.existsSync(DOWNLOADS_DIR)) {
    fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
  }
}

function cleanupFiles(...files) {
  for (const f of files) {
    if (f && fs.existsSync(f)) fs.unlinkSync(f);
  }
}

// Converte vídeo/gif → GIF 512x512 com paleta preservada
async function convertVideoToGif(inputPath, outputPath, fps = 12) {

  const clampedFps = Math.min(fps, 12);

  const filter = [
    `fps=${clampedFps},scale=512:512:flags=lanczos,split[s0][s1]`,
    `[s0]palettegen=max_colors=256:reserve_transparent=1[p]`,
    `[s1][p]paletteuse=dither=bayer`
  ].join(";");

  await execFileAsync(FFMPEG, [
    "-i", inputPath,
    "-filter_complex", filter,  // <-- era -vf, tem que ser -filter_complex pro split funcionar
    "-loop", "0",
    "-y",
    outputPath
  ]);
}

// Força imagem estática para 512x512
async function resizeToSticker(inputPath, outputPath) {

  await execFileAsync(FFMPEG, [
    "-i", inputPath,
    "-vf", "scale=512:512:flags=lanczos",  // lanczos = melhor qualidade no resize
    "-y",
    outputPath
  ]);

}

async function createStickerWithFallback(stickerInputPath, isAnimated) {

  const qualities = [80, 60, 40, 20];

  for (const quality of qualities) {

    const buffer = await createSticker(
      fs.readFileSync(stickerInputPath),
      {
        pack: "Criada por ManyBot\n",
        author: "\ngithub.com/synt-xerror/manybot",
        type: isAnimated ? "FULL" : "STATIC",
        categories: ["🤖"],
        quality,
      }
    );

    if (buffer.length <= MAX_STICKER_SIZE) {
      return buffer;
    }

  }

  throw new Error("Não foi possível reduzir o sticker para menos de 900 KB.");
}

// ───────────────── Sessão ─────────────────

export function iniciarSessao(chatId, author) {

  if (stickerSessions.has(chatId)) return false;

  const timeout = setTimeout(() => {

    stickerSessions.delete(chatId);
    client.sendMessage(chatId, botMsg("Sessão de figurinha expirou."));

  }, SESSION_TIMEOUT);

  stickerSessions.set(chatId, {
    author,
    medias: [],
    timeout
  });

  return true;

}

// ───────────────── Coleta de mídia ─────────────────

export async function coletarMidia(msg) {

  const chat = await msg.getChat();
  const chatId = chat.id._serialized;

  const session = stickerSessions.get(chatId);
  if (!session) return;

  const sender = msg.author || msg.from;
  if (sender !== session.author) return;
  if (!msg.hasMedia) return;

  const media = await msg.downloadMedia();
  if (!media) return;

  const isGif =
    media.mimetype === "image/gif" ||
    (media.mimetype === "video/mp4" && msg._data?.isGif);

  if (
    !media.mimetype ||
    (!media.mimetype.startsWith("image/") &&
     !media.mimetype.startsWith("video/") &&
     !isGif)
  ) {
    return;
  }

  if (session.medias.length < MAX_MEDIA) {
    session.medias.push(media);
  }

}

// ───────────────── Criar stickers ─────────────────

export async function gerarSticker(msg, chatId) {

  const sender = msg.author || msg.from;
  const session = stickerSessions.get(chatId);

  if (!session) {
    return msg.reply(botMsg("Nenhuma sessão de figurinha ativa."));
  }

  if (session.author !== sender) {
    return msg.reply(botMsg("Apenas quem iniciou a sessão pode criar as figurinhas."));
  }

  const medias = session.medias;

  if (!medias.length) {
    return msg.reply(botMsg("Nenhuma imagem recebida."));
  }

  clearTimeout(session.timeout);

  console.log("midias:", medias.length);

  await msg.reply(botMsg("Aguarde! Estou criando as suas figurinhas..."));

  ensureDownloadsDir();

    for (const media of medias) {
    try {
      const ext = media.mimetype.split("/")[1];
      const isVideo = media.mimetype.startsWith("video/");
      const isGif = media.mimetype === "image/gif";
      const isAnimated = isVideo || isGif;

      const id = Date.now() + "-" + Math.random().toString(36).slice(2);
      const inputPath = path.join(DOWNLOADS_DIR, `${id}.${ext}`);
      const gifPath = path.join(DOWNLOADS_DIR, `${id}.gif`);
      const resizedPath = path.join(DOWNLOADS_DIR, `${id}-scaled.${ext}`);

      fs.writeFileSync(inputPath, Buffer.from(media.data, "base64"));

      // LOG 1 — arquivo de entrada
      const inputSize = fs.statSync(inputPath).size;
      console.log(`[1] mimetype: ${media.mimetype} | isAnimated: ${isAnimated} | inputPath: ${inputPath} | size: ${inputSize} bytes`);

      let stickerInputPath = inputPath;

      if (isAnimated) {
        console.log("[2] Convertendo para GIF...");
        await convertVideoToGif(inputPath, gifPath, isVideo ? 12 : 24);

        // LOG 2 — gif gerado
        if (fs.existsSync(gifPath)) {
          console.log(`[2] GIF gerado: ${fs.statSync(gifPath).size} bytes`);
        } else {
          console.error("[2] ERRO: gifPath não foi criado pelo ffmpeg!");
        }

        stickerInputPath = gifPath;
      } else {
        console.log("[2] Redimensionando imagem estática...");
        await resizeToSticker(inputPath, resizedPath);

        if (fs.existsSync(resizedPath)) {
          console.log(`[2] Resized gerado: ${fs.statSync(resizedPath).size} bytes`);
        } else {
          console.error("[2] ERRO: resizedPath não foi criado!");
        }

        stickerInputPath = resizedPath;
      }

      // LOG 3 — antes de criar o sticker
      console.log(`[3] stickerInputPath: ${stickerInputPath} | exists: ${fs.existsSync(stickerInputPath)} | size: ${fs.existsSync(stickerInputPath) ? fs.statSync(stickerInputPath).size : "N/A"} bytes`);

      const stickerBuffer = await createStickerWithFallback(stickerInputPath, isAnimated);

      // LOG 4 — sticker gerado
      console.log(`[4] Sticker buffer: ${stickerBuffer.length} bytes`);

      const stickerMedia = new MessageMedia("image/webp", stickerBuffer.toString("base64"));
      await client.sendMessage(chatId, stickerMedia, { sendMediaAsSticker: true });

      cleanupFiles(inputPath, gifPath, resizedPath);

    } catch (err) {
      console.error("Erro ao gerar sticker:", err);
      await msg.reply(botMsg("Erro ao gerar uma das figurinhas."));
    }
  }

  await msg.reply(botMsg("Figurinhas geradas com sucesso!"));

  stickerSessions.delete(chatId);
  emptyFolder("downloads");

}