const express = require("express");
const { eventsHandler, sendLogToClients } = require("./sse");
const puppeteer = require("puppeteer");
const fs = require("fs");
const path = require("path");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();
const PORT = 3001;

app.use(bodyParser.json());

// Buat folder sesi kalau belum ada
if (!fs.existsSync(path.join(__dirname, "sessions"))) {
  fs.mkdirSync(path.join(__dirname, "sessions"));
}

app.use(
  cors({
    origin: "http://127.0.0.1:8000/", // atau spesifik: 'http://127.0.0.1:8000'
    methods: ["GET", "POST"],
    allowedHeaders: ["Content-Type"],
  })
);

// Atau jika tidak pakai cors package:
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*"); // Ganti '*' dengan origin spesifik kalau perlu
  res.setHeader("Access-Control-Allow-Methods", "GET, POST");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
  next();
});

app.get("/logs", eventsHandler);

app.post("/instagram/comment", async (req, res) => {
  const { ig_username, ig_password, post_url, comment } = req.body;
  // sendLogToClients("📦 Payload diterima:", req.body);
  sendLogToClients(`📦 Payload diterima: ${JSON.stringify(req.body)}`);
  const SESSION_FILE_PATH = path.join(
    __dirname,
    "sessions",
    `${ig_username}.json`
  );

  try {
    const browser = await puppeteer.launch({
      headless: true,
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });

    const page = await browser.newPage();
    await page.setUserAgent(
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    );
    await page.setViewport({ width: 1280, height: 800 });

    let loggedIn = false;
    if (fs.existsSync(SESSION_FILE_PATH)) {
      const cookies = JSON.parse(fs.readFileSync(SESSION_FILE_PATH));
      await page.setCookie(...cookies);
      sendLogToClients("✅ Sesi login dimuat");
    }

    await page.goto("https://www.instagram.com/", {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    loggedIn = await page.evaluate(() => {
      return !!document.querySelector(
        'svg[aria-label="Beranda"], svg[aria-label="Home"]'
      );
    });

    if (!loggedIn) {
      sendLogToClients("🔐 Login ulang...");
      await page.goto("https://www.instagram.com/accounts/login/", {
        waitUntil: "networkidle2",
      });

      await page.waitForSelector('input[name="username"]', { timeout: 15000 });
      await page.type('input[name="username"]', ig_username, { delay: 100 });
      await page.type('input[name="password"]', ig_password, { delay: 100 });
      await page.keyboard.press("Enter");

      await page
        .waitForNavigation({ waitUntil: "networkidle2", timeout: 15000 })
        .catch(() => {});
      await new Promise((resolve) => setTimeout(resolve, 4000));

      if (page.url().includes("/onetap")) {
        sendLogToClients(
          "🔁 Redirect dari Instagram One Tap, alihkan ke beranda..."
        );
        await page.goto("https://www.instagram.com/", {
          waitUntil: "networkidle2",
        });
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }

      const loginFailed = await page.evaluate(() => {
        return (
          document.body.innerText.includes("kata sandi Anda salah") ||
          document.body.innerText.includes("Your password was incorrect") ||
          document.body.innerText.includes("Try again")
        );
      });

      if (loginFailed) {
        throw new Error("Login gagal: username atau password salah");
      }

      const cookies = await page.cookies();
      fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(cookies, null, 2));
      sendLogToClients("💾 Sesi login disimpan");
    }

    // Kunjungi postingan
    await page.goto(post_url, { waitUntil: "networkidle2" });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    await page.evaluate(() => window.scrollBy(0, window.innerHeight));
    await new Promise((resolve) => setTimeout(resolve, 2000));

    await page.screenshot({ path: "debug_screenshot.png", fullPage: true });

    const commentBoxSelector = "form textarea";
    await page.waitForSelector(commentBoxSelector, { timeout: 15000 });

    await page.click(commentBoxSelector);
    await page.type(commentBoxSelector, comment, { delay: 50 });

    await new Promise((resolve) => setTimeout(resolve, 2000));
    await page.keyboard.press("Enter");

    sendLogToClients("✅ Berhasil mengirim komentar!");
    sendLogToClients("===============================");
    res.json({ success: true, message: "✅ Berhasil mengirim komentar!" });
    await browser.close();
  } catch (error) {
    console.error("❌ ERROR:", error);
    res.status(500).json({
      success: false,
      message: "Gagal kirim komentar",
      error: error.message,
    });
  }
});

// 🔴 ENDPOINT REPORT
app.post("/instagram/report", async (req, res) => {
  const { ig_username, ig_password, target_username } = req.body;
  sendLogToClients(`📦 Payload diterima: ${JSON.stringify(req.body)}`);
  const SESSION_FILE_PATH = path.join(
    __dirname,
    "sessions",
    `${ig_username}.json`
  );

  let browser;
  let page;

  try {
    browser = await puppeteer.launch({
      headless: true,
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });

    page = await browser.newPage();
    await page.setUserAgent(
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    );
    await page.setViewport({ width: 1280, height: 800 });

    if (fs.existsSync(SESSION_FILE_PATH)) {
      const cookies = JSON.parse(fs.readFileSync(SESSION_FILE_PATH));
      await page.setCookie(...cookies);
      sendLogToClients("✅ Sesi login dimuat");
    }

    await page.goto("https://www.instagram.com/", {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    const loggedIn = await page.evaluate(() => {
      return !!document.querySelector(
        'svg[aria-label="Beranda"], svg[aria-label="Home"]'
      );
    });

    if (!loggedIn) {
      sendLogToClients("🔐 Login ulang...");
      await page.goto("https://www.instagram.com/accounts/login/", {
        waitUntil: "networkidle2",
      });

      await page.waitForSelector('input[name="username"]', { timeout: 15000 });
      await page.type('input[name="username"]', ig_username, { delay: 100 });
      await page.type('input[name="password"]', ig_password, { delay: 100 });
      await page.keyboard.press("Enter");

      await page
        .waitForNavigation({ waitUntil: "networkidle2", timeout: 15000 })
        .catch(() => {});
      await new Promise((resolve) => setTimeout(resolve, 4000));

      if (page.url().includes("/onetap")) {
        await page.goto("https://www.instagram.com/", {
          waitUntil: "networkidle2",
        });
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }

      const loginFailed = await page.evaluate(() => {
        return (
          document.body.innerText.includes("kata sandi Anda salah") ||
          document.body.innerText.includes("Your password was incorrect") ||
          document.body.innerText.includes("Try again")
        );
      });

      if (loginFailed) {
        throw new Error("Login gagal: username atau password salah");
      }

      const cookies = await page.cookies();
      fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(cookies, null, 2));
      sendLogToClients("💾 Sesi login disimpan");
    }

    // Kunjungi profil target
    await page.goto(`https://www.instagram.com/${target_username}/`, {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    // Klik ikon "Options"
    const optionsButton = await page.$('svg[aria-label="Options"]');
    if (!optionsButton) {
      throw new Error('Tidak menemukan ikon "Options"');
    }
    await optionsButton.evaluate((el) => el.parentElement.click());
    sendLogToClients('📌 Ikon "Options" diklik');

    // Klik "Report"
    await page.waitForSelector('div[role="dialog"] button');
    await clickButtonByText(page, ["report", "laporkan"]);

    // Klik "Report Account"
    await page.waitForSelector('div[role="dialog"] button');
    await clickButtonByText(page, ["report account", "laporkan akun"]);

    // Klik "It’s pretending to be someone else"
    await page.waitForSelector('div[role="dialog"] button');
    await clickButtonByText(page, [
      "pretending to be someone else",
      "menyamar sebagai orang lain",
    ]);

    // Klik "A celebrity or public figure"
    await page.waitForSelector('div[role="dialog"]');
    await clickRadioOptionByText(page, [
      "Someone I follow",
      "seseorang yang saya ikuti",
    ]);

    // Klik Submit
    await page.waitForSelector('div[role="dialog"] button');
    await clickButtonByText(page, [
      "submit report",
      "kirim laporan",
      "done",
      "selesai",
    ]);

    // Tambahan untuk memilih akun yang ditiru
    await page.waitForSelector("input[placeholder]", { timeout: 10000 });
    await page.type("input[placeholder]", "zaidan_yahyaa", { delay: 100 });
    sendLogToClients('⌨️ Mengetik "zaidan_yahyaa" di kolom pencarian');

    // Tunggu tombol "Next" muncul
    await page.waitForFunction(
      () => {
        const buttons = Array.from(
          document.querySelectorAll('div[role="dialog"] button')
        );
        return buttons.some(
          (btn) => btn.innerText.trim().toLowerCase() === "next"
        );
      },
      { timeout: 10000 }
    );

    // Ambil semua tombol "Next" lalu klik yang pertama
    const nextButtons = await page.$$('div[role="dialog"] button');
    let clicked = false;

    for (const btn of nextButtons) {
      const text = await btn.evaluate((el) =>
        el.innerText.trim().toLowerCase()
      );
      if (text === "next") {
        await btn.click();
        clicked = true;
        sendLogToClients('➡️ Klik tombol "Next" pertama di hasil pencarian');
        break;
      }
    }

    if (!clicked) {
      throw new Error('Tidak menemukan tombol "Next" dengan teks yang sesuai');
    }

    await new Promise((resolve) => setTimeout(resolve, 5000));
    sendLogToClients("✅ Pelaporan berhasil!");
    sendLogToClients("=======================");
    res.json({ success: true, message: "✅ Pelaporan berhasil!" });

    await browser.close();
  } catch (error) {
    console.error("❌ ERROR REPORT:", error);
    if (page) {
      await page
        .screenshot({ path: "report_error.png", fullPage: true })
        .catch(() => {});
    }
    if (browser) await browser.close();
    res.status(500).json({
      success: false,
      message: "Gagal melakukan report",
      error: error.message,
    });
  }
});

// Fungsi bantu klik tombol berdasarkan teks
async function clickButtonByText(page, texts, retries = 5) {
  texts = texts.map((t) => t.toLowerCase());

  for (let attempt = 0; attempt < retries; attempt++) {
    const buttons = await page.$$('div[role="dialog"] button');
    for (const btn of buttons) {
      const text = await (await btn.getProperty("innerText")).jsonValue();
      if (text && texts.some((t) => text.toLowerCase().includes(t))) {
        await btn.click();
        await new Promise((r) => setTimeout(r, 1000));
        sendLogToClients(`📌 Klik tombol: ${text}`);
        return;
      }
    }

    // Tunggu sebentar sebelum mencoba lagi
    await new Promise((r) => setTimeout(r, 2000));
  }

  throw new Error(`Tombol dengan teks [${texts.join(", ")}] tidak ditemukan`);
}

async function clickRadioOptionByText(page, texts) {
  texts = texts.map((t) => t.trim().toLowerCase());

  // Ambil semua div yang berisi teks opsi
  const radioElements = await page.$$('div[role="dialog"] div._abn2');

  // sendLogToClients(`🔍 Ditemukan ${radioElements.length} kandidat elemen opsi`);

  for (const el of radioElements) {
    const text = await (await el.getProperty("innerText")).jsonValue();
    const cleanText = text.trim().toLowerCase();

    // sendLogToClients("🪪 Opsi:", cleanText);

    if (texts.includes(cleanText)) {
      await el.click();
      sendLogToClients(`📌 Opsi radio dipilih: ${text}`);
      return;
    }
  }

  throw new Error(
    `Opsi radio dengan teks [${texts.join(", ")}] tidak ditemukan`
  );
}

app.post("/tiktok/comment", async (req, res) => {
  const { tt_username, tt_password, post_url, comment } = req.body;
  sendLogToClients(`📦 Payload diterima: ${JSON.stringify(req.body)}`);

  const SESSION_FILE_PATH = path.join(
    __dirname,
    "sessions",
    `${tt_username}_tiktok.json`
  );

  try {
    const browser = await puppeteer.launch({
      headless: true,
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });

    const page = await browser.newPage();
    await page.setUserAgent(
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    );
    await page.setViewport({ width: 1280, height: 800 });

    // Load session cookies
    let loggedIn = false;
    if (fs.existsSync(SESSION_FILE_PATH)) {
      const cookies = JSON.parse(fs.readFileSync(SESSION_FILE_PATH));
      await page.setCookie(...cookies);
      sendLogToClients("✅ Sesi login TikTok dimuat");
    }

    await page.goto("https://www.tiktok.com/", {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    // Cek login
    loggedIn = await page.evaluate(() => {
      return !!document.querySelector('div[data-e2e="profile-icon"]');
    });

    if (!loggedIn) {
      sendLogToClients("🔐 Login ulang ke TikTok...");

      await page.goto("https://www.tiktok.com/login/phone-or-email/email", {
        waitUntil: "networkidle2",
      });

      await page.waitForSelector('input[name="username"]', { timeout: 15000 });
      await page.type('input[name="username"]', tt_username, { delay: 100 });
      await page.type('input[type="password"]', tt_password, { delay: 100 });

      const loginBtn = await page.$('button[type="submit"]');
      if (loginBtn) await loginBtn.click();

      await page
        .waitForNavigation({ waitUntil: "networkidle2", timeout: 15000 })
        .catch(() => {});
      await new Promise((resolve) => setTimeout(resolve, 5000));

      // Deteksi kegagalan login
      const loginFailed = await page.evaluate(() => {
        return (
          document.body.innerText.includes("incorrect") ||
          document.body.innerText.includes("salah")
        );
      });

      if (loginFailed) {
        throw new Error("Login TikTok gagal: username atau password salah");
      }

      const cookies = await page.cookies();
      fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(cookies, null, 2));
      sendLogToClients("💾 Sesi login TikTok disimpan");
    }

    // Kunjungi postingan TikTok
    await page.goto(post_url, { waitUntil: "networkidle2" });
    await new Promise((resolve) => setTimeout(resolve, 3000));
    sendLogToClients("🔎 Mengakses postingan...");

    // Klik untuk aktifkan kolom komentar
    await page.waitForSelector(
      "div.public-DraftStyleDefault-block.public-DraftStyleDefault-ltr",
      { timeout: 15000 }
    );

    const commentBox = await page.$(
      "div.public-DraftStyleDefault-block.public-DraftStyleDefault-ltr"
    );
    if (!commentBox) {
      throw new Error("❌ Kolom komentar tidak ditemukan.");
    }

    await commentBox.focus();
    await page.keyboard.type(comment, { delay: 50 });
    await new Promise((resolve) => setTimeout(resolve, 1000));

    // Klik tombol kirim
    const sendButton = await page.$(
      'div[data-e2e="comment-post"][aria-label="Post"][role="button"]'
    );
    if (sendButton) {
      await sendButton.click();
      await new Promise((resolve) => setTimeout(resolve, 5000));
      sendLogToClients("✅ Komentar berhasil dikirim!");
    } else {
      throw new Error("❌ Tombol kirim komentar tidak ditemukan.");
    }

    sendLogToClients("===============================");
    res.json({
      success: true,
      message: "✅ Berhasil mengirim komentar ke TikTok!",
    });
    await browser.close();
  } catch (error) {
    console.error("❌ ERROR:", error);
    console.log(`❌ ERROR: ${error.message}`);
    res.status(500).json({
      success: false,
      message: "Gagal kirim komentar TikTok",
      error: error.message,
    });
  }
});

app.post("/tiktok/report", async (req, res) => {
  const { tt_username, tt_password, target_username } = req.body;
  sendLogToClients(`📦 Payload diterima: ${JSON.stringify(req.body)}`);

  const SESSION_FILE_PATH = path.join(
    __dirname,
    "sessions",
    `${tt_username}_tiktok.json`
  );

  try {
    const browser = await puppeteer.launch({
      headless: true,
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
    });

    const page = await browser.newPage();
    await page.setUserAgent(
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    );
    await page.setViewport({ width: 1280, height: 800 });

    // Load session cookies
    let loggedIn = false;
    if (fs.existsSync(SESSION_FILE_PATH)) {
      const cookies = JSON.parse(fs.readFileSync(SESSION_FILE_PATH));
      await page.setCookie(...cookies);
      sendLogToClients("✅ Sesi login TikTok dimuat");
    }

    await page.goto("https://www.tiktok.com/", {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    // Cek login
    loggedIn = await page.evaluate(() => {
      return !!document.querySelector('div[data-e2e="profile-icon"]');
    });

    if (!loggedIn) {
      sendLogToClients("🔐 Login ulang ke TikTok...");

      await page.goto("https://www.tiktok.com/login/phone-or-email/email", {
        waitUntil: "networkidle2",
      });

      await page.waitForSelector('input[name="username"]', { timeout: 15000 });
      await page.type('input[name="username"]', tt_username, { delay: 100 });
      await page.type('input[type="password"]', tt_password, { delay: 100 });

      const loginBtn = await page.$('button[type="submit"]');
      if (loginBtn) await loginBtn.click();

      await page
        .waitForNavigation({ waitUntil: "networkidle2", timeout: 15000 })
        .catch(() => {});
      await new Promise((resolve) => setTimeout(resolve, 5000));

      // Deteksi kegagalan login
      const loginFailed = await page.evaluate(() => {
        return (
          document.body.innerText.includes("incorrect") ||
          document.body.innerText.includes("salah")
        );
      });

      if (loginFailed) {
        throw new Error("Login TikTok gagal: username atau password salah");
      }

      const cookies = await page.cookies();
      fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(cookies, null, 2));
      sendLogToClients("💾 Sesi login TikTok disimpan");
    }

    // Kunjungi profil target
    await page.goto(`https://www.tiktok.com/@${target_username}`, {
      waitUntil: "networkidle2",
    });
    await new Promise((resolve) => setTimeout(resolve, 4000));

    const targetUsername = "zaidan_yahyaa"; // <- didefinisikan di dalam fungsi

    // 1. Klik tombol titik tiga (options)
    const moreButton = await page.$('button[data-e2e="user-more"]');
    if (!moreButton) throw new Error("Tombol titik tiga tidak ditemukan");
    await moreButton.click();
    await new Promise((resolve) => setTimeout(resolve, 2000));

    // 2. Klik tombol "Report"
    const reportTrigger = await page.$('div[aria-label="Report"]');
    if (!reportTrigger) throw new Error("Tombol 'Report' tidak ditemukan");
    await reportTrigger.click();
    await new Promise((resolve) => setTimeout(resolve, 2000));

    // 3. Klik "Report account"
    const reportAccountOption = await page.$$(
      'label[data-e2e="report-card-reason"]'
    );
    if (reportAccountOption.length < 1)
      throw new Error("Opsi 'Report account' tidak ditemukan");
    await reportAccountOption[0].click(); // asumsikan opsi pertama adalah 'Report account'
    await new Promise((resolve) => setTimeout(resolve, 1500));

    // 4. Klik "Pretending to be someone"
    await page.waitForSelector('label[data-e2e="report-card-reason"]');

    const options = await page.$$('label[data-e2e="report-card-reason"]');
    for (const option of options) {
      const text = await page.evaluate((el) => el.textContent, option);
      if (text.includes("Menyamar") || text.includes("Pretending")) {
        await option.click();
        await new Promise((resolve) => setTimeout(resolve, 1500));
        break;
      }
    }

    // 5. Klik "Celebrity"
    await page.waitForSelector('label[data-e2e="report-card-reason"]');

    const reportOptions = await page.$$('label[data-e2e="report-card-reason"]');

    let foundCelebrity = false;
    for (const option of reportOptions) {
      const text = await page.evaluate((el) => el.textContent, option);
      if (text.includes('Selebritas') || text.includes('Celebrity')) {
        await option.click();
        await new Promise((resolve) => setTimeout(resolve, 1500));
        foundCelebrity = true;
        break;
      }
    }

    if (!foundCelebrity) {
      throw new Error("Opsi 'Celebrity' tidak ditemukan");
    }

    // 6. Isi form username
    const inputField = await page.$(
      'input[placeholder="Search for user name"]'
    );
    if (!inputField)
      throw new Error("Kolom pencarian username tidak ditemukan");
    await inputField.type(targetUsername);
    await new Promise((resolve) => setTimeout(resolve, 2000));

    // 7. Klik akun pertama yang muncul
    const firstAccount = await page.$("li.css-6dke92-LiUser");
    if (!firstAccount)
      throw new Error("Akun tidak ditemukan dalam hasil pencarian");
    await firstAccount.click();
    await new Promise((resolve) => setTimeout(resolve, 1500));

    // 8. Klik tombol Submit
    const submitButton = await page.$("button.css-wwwrxx-ButtonSubmit");
    if (!submitButton) throw new Error("Tombol Submit tidak ditemukan");
    await submitButton.click();
    await new Promise((resolve) => setTimeout(resolve, 5000));
    sendLogToClients("✅ Pelaporan berhasil!");
    sendLogToClients("=======================");
    res.json({ success: true, message: "\u2705 Pelaporan berhasil!" });

    await browser.close();
  } catch (error) {
    console.error("\u274c ERROR REPORT:", error);
    if (page) {
      await page
        .screenshot({ path: "tiktok_report_error.png", fullPage: true })
        .catch(() => {});
    }
    if (browser) await browser.close();
    res.status(500).json({
      success: false,
      message: "Gagal melakukan report di TikTok",
      error: error.message,
    });
  }
});

app.listen(PORT, () => {
  console.log(`🚀 Bot berjalan di http://localhost:${PORT}`);
});
