const TelegramBot = require("node-telegram-bot-api");
const axios = require("axios");
const { NodeSSH } = require("node-ssh");
const fs = require("fs");
const fse = require("fs-extra");
const archiver = require("archiver");

/* =========================
   ENV
========================= */
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
const OWNER_ID = String(process.env.TELEGRAM_OWNER_ID || "");
const CHANNEL_ID = process.env.TELEGRAM_CHANNEL_ID || null;
const API_BASE_URL = process.env.API_BASE_URL;

let bot = null;

/* =========================
   UTIL
========================= */
function rupiah(n) {
  return `Rp ${Number(n || 0).toLocaleString("id-ID")}`;
}

/* =========================
   SAFE SEND
========================= */
async function safeSend(chatId, text, opts = {}) {
  try {
    return await bot.sendMessage(chatId, text, opts);
  } catch {
    if (String(chatId) !== OWNER_ID) {
      return bot.sendMessage(OWNER_ID, text, opts);
    }
  }
}

/* =========================
   SSH MAINTENANCE (FRONTEND VPS)
========================= */
async function setMaintenance(mode) {
  const ssh = new NodeSSH();

  await ssh.connect({
    host: process.env.FRONTEND_HOST,
    username: process.env.FRONTEND_USER,
    privateKeyPath: process.env.FRONTEND_KEY
  });

  const cmd =
    mode === "on"
      ? "touch /var/www/nexpay/nexpay/maintenance.lock"
      : "rm -f /var/www/nexpay/nexpay/maintenance.lock";

  const result = await ssh.execCommand(cmd);

  ssh.dispose();
  return result;
}

/* =========================
   FORMAT MAINTENANCE MESSAGE
========================= */

function formatMaintenanceAlert(mode, estimasi) {
  const now = new Date().toLocaleString("id-ID", {
    timeZone: "Asia/Jakarta"
  });

  const isOn = mode === "on";

  return `
<b>STATUS SISTEM</b>

<b>Status:</b> ${isOn ? "SEDANG MAINTENANCE" : "NORMAL"}
<b>Waktu:</b> ${now}${isOn && estimasi ? `\n<b>Estimasi:</b> ${estimasi}` : ""}

${isOn
  ? "Sedang dilakukan maintenance sistem untuk sementara waktu."
  : "Maintenance telah selesai. Sistem kembali normal."}

<b>Dampak:</b>
${isOn
  ? "• Layanan sementara tidak dapat digunakan\n• Mohon tunggu beberapa saat"
  : "• Tidak ada dampak\n• Semua layanan berjalan normal"}
`.trim();
}

/* =========================
   SEND CHANNEL (NO EDIT, ALWAYS NEW MESSAGE)
========================= */

async function sendChannelMessage(mode, estimasi) {
  if (!bot || !CHANNEL_ID) return;

  const text = formatMaintenanceAlert(mode, estimasi);

  await bot.sendMessage(CHANNEL_ID, text, {
    parse_mode: "HTML"
  });
}

/* =========================
   BACKUP BACKEND (LOCAL)
========================= */
async function backupBackend() {
  const zipPath = `/tmp/backend_${Date.now()}.zip`;

  await new Promise((resolve, reject) => {
    const output = fs.createWriteStream(zipPath);
    const archive = archiver("zip", { zlib: { level: 9 } });

    output.on("close", resolve);
    archive.on("error", reject);

    archive.pipe(output);
    archive.directory("/root/Backend", false);
    archive.finalize();
  });

  await bot.sendDocument(
    OWNER_ID,
    zipPath,
    {
      caption: "📦 Backup Backend",
      contentType: "application/zip"
    }
  );

  await fse.remove(zipPath);
}

/* =========================
   BACKUP FRONTEND (REMOTE VPS)
========================= */
async function backupFrontend() {
  const ssh = new NodeSSH();
  const ts = Date.now();

  const remoteZip = `/tmp/frontend_${ts}.zip`;
  const localZip = `/tmp/frontend_${ts}.zip`;

  await ssh.connect({
    host: process.env.FRONTEND_HOST,
    username: process.env.FRONTEND_USER,
    privateKeyPath: process.env.FRONTEND_KEY
  });

  await ssh.execCommand(
    `zip -r ${remoteZip} /var/www/nexpay/nexpay >/dev/null 2>&1`
  );

  await ssh.getFile(localZip, remoteZip);
  await ssh.execCommand(`rm -f ${remoteZip}`);
  ssh.dispose();

  await bot.sendDocument(
    OWNER_ID,
    localZip,
    {
      caption: "📦 Backup Frontend",
      contentType: "application/zip"
    }
  );

  await fse.remove(localZip);
}

/* =========================
   INIT BOT
========================= */
function initTelegramBot({ approveWithdraw, rejectWithdraw }) {
  if (!BOT_TOKEN || !OWNER_ID) {
    console.log("Telegram bot belum dikonfigurasi");
    return;
  }

  bot = new TelegramBot(BOT_TOKEN, { polling: true });

  /* ===== BACKUP COMMAND ===== */
  bot.onText(/^\/backup$/, async (msg) => {
    if (String(msg.from.id) !== OWNER_ID) {
      return bot.sendMessage(msg.chat.id, "Khusus owner");
    }

    try {
      await safeSend(msg.chat.id, "⏳ Backup frontend...");
      await backupFrontend();

      await safeSend(msg.chat.id, "⏳ Backup backend...");
      await backupBackend();

      await safeSend(msg.chat.id, "✅ Backup selesai (2 file dikirim)");
    } catch (err) {
      console.error("Backup error:", err);
      bot.sendMessage(msg.chat.id, "❌ Backup gagal");
    }
  });

  /* ===== POPUP ===== */
  bot.onText(/\/popup (on|off)([\s\S]*)/, async (msg, match) => {
    const chatId = msg.chat.id;
    const mode = match[1];
    const text = (match[2] || "").trim();

    if (mode === "off") {
      await axios.post(`${API_BASE_URL}/internal/info-popup`, {
        secret: process.env.BOT_INTERNAL_SECRET,
        active: false
      });
      return bot.sendMessage(chatId, "Popup berhasil dimatikan");
    }

    const [title, ...rest] = text.split("|");
    const message = rest.join("|");

    if (!title || !message) {
      return bot.sendMessage(chatId, "Format salah\n\n/popup on Judul|Isi");
    }

    await axios.post(`${API_BASE_URL}/internal/info-popup`, {
      secret: process.env.BOT_INTERNAL_SECRET,
      active: true,
      title: title.trim(),
      message: message.trim()
    });

    bot.sendMessage(chatId, "Popup berhasil diaktifkan");
  });

  /* ===== MAINTENANCE ===== */
  bot.onText(/^\/maintenance (on|off)(.*)$/i, async (msg, match) => {
    if (String(msg.from.id) !== OWNER_ID) {
      return bot.sendMessage(msg.chat.id, "Khusus owner");
    }

    const mode = match[1].toLowerCase();
    const estimasi = (match[2] || "").trim();

    try {
      await setMaintenance(mode);

      // 🔥 kirim message BARU ke channel (NO EDIT)
      await sendChannelMessage(mode, estimasi);

      return bot.sendMessage(
        msg.chat.id,
        mode === "on"
          ? "✅ Maintenance ON (notifikasi terkirim)"
          : "✅ Maintenance OFF (notifikasi terkirim)"
      );

    } catch (err) {
      console.log("Maintenance error:", err.message);
      return bot.sendMessage(msg.chat.id, "❌ Gagal ubah maintenance");
    }
  });

  /* ===== CALLBACK QUERY ===== */
  bot.on("callback_query", async (query) => {
    try {
      const userId = String(query.from.id);
      const chatId = query.message.chat.id;
      const messageId = query.message.message_id;
      const data = query.data || "";

      if (userId !== OWNER_ID) {
        return bot.answerCallbackQuery(query.id, {
          text: "Khusus owner",
          show_alert: true
        });
      }

      if (data.startsWith("wd_approve_")) {
        const id = data.replace("wd_approve_", "");
        const result = approveWithdraw(id);

        await bot.answerCallbackQuery(query.id, { text: result.message });

        await bot.editMessageText(
          result.success
            ? `✅ <b>WITHDRAW APPROVED</b>\n\n<b>ID:</b> <code>${id}</code>`
            : `❌ <b>GAGAL</b>\n\n${result.message}`,
          { chat_id: chatId, message_id: messageId, parse_mode: "HTML" }
        );
      }

      if (data.startsWith("wd_reject_")) {
        const id = data.replace("wd_reject_", "");
        const result = rejectWithdraw(id);

        await bot.answerCallbackQuery(query.id, { text: result.message });

        await bot.editMessageText(
          result.success
            ? `❌ <b>WITHDRAW REJECTED</b>\n\n<b>ID:</b> <code>${id}</code>\nSaldo dikembalikan.`
            : `❌ <b>GAGAL</b>\n\n${result.message}`,
          { chat_id: chatId, message_id: messageId, parse_mode: "HTML" }
        );
      }
    } catch (err) {
      console.error("Callback error:", err);
    }
  });

  console.log("Telegram owner bot aktif");
}

/* =========================
   WITHDRAW REQUEST
========================= */
async function sendWithdrawRequest(withdraw, merchant) {
  if (!bot || !OWNER_ID) return;

  const text = `
<b>🔔 REQUEST WITHDRAW BARU</b>

<b>Merchant:</b> ${merchant.name}
<b>Email:</b> ${merchant.email}

<b>ID WD:</b> <code>${withdraw.withdraw_id}</code>
<b>Nominal:</b> ${rupiah(withdraw.amount)}
<b>Metode:</b> ${withdraw.method}
<b>Provider:</b> ${withdraw.provider}
<b>Nama:</b> ${withdraw.account_name}
<b>Nomor:</b> <code>${withdraw.account_number}</code>

<b>Status:</b> PENDING
`;

  await bot.sendMessage(OWNER_ID, text, {
    parse_mode: "HTML",
    reply_markup: {
      inline_keyboard: [[
        { text: "APPROVE", callback_data: `wd_approve_${withdraw.withdraw_id}` },
        { text: "REJECT", callback_data: `wd_reject_${withdraw.withdraw_id}` }
      ]]
    }
  });
}

module.exports = {
  initTelegramBot,
  sendWithdrawRequest
};
