import fs from "node:fs";
import process from "node:process";
import { chromium } from "playwright-core";
import { createChatServer } from "../server.js";

const chromeCandidates = [
  process.env.CHROME_PATH,
  "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
  "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
  "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
  "/usr/bin/google-chrome",
  "/usr/bin/chromium",
  "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
].filter(Boolean);

const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candidate));
if (!executablePath) {
  throw new Error("Chrome/Edge was not found. Set CHROME_PATH before running npm run check.");
}

fs.rmSync(new URL("../data/db.json", import.meta.url), { force: true });

const server = await createChatServer({ host: "127.0.0.1", port: 0 });
const baseUrl = `http://127.0.0.1:${server.port}`;

let browser;
const runtimeErrors = [];

function assert(condition, message) {
  if (!condition) throw new Error(message);
}

async function signUp(context, { username, password, name }) {
  const page = await context.newPage();
  page.on("pageerror", (error) => runtimeErrors.push(`${username}: ${error.message}`));
  await page.goto(baseUrl, { waitUntil: "networkidle" });
  await page.click("#signupButton");
  await page.fill("#displayName", name);
  await page.fill("#username", username);
  await page.fill("#password", password);
  await page.click(".login-button");
  await page.waitForURL("**/chat.html", { timeout: 10000 });
  await page.waitForSelector(".contact-item, .empty-contacts", { timeout: 10000 });
  return page;
}

try {
  browser = await chromium.launch({ executablePath, headless: true });

  const firstContext = await browser.newContext({
    locale: "fa-IR",
    viewport: { width: 1280, height: 800 },
  });
  const secondContext = await browser.newContext({
    locale: "fa-IR",
    viewport: { width: 1280, height: 800 },
  });

  /* حساب اول */
  const amirali = await signUp(firstContext, {
    username: "amirali",
    password: "1234",
    name: "امیرعلی",
  });
  assert(
    (await amirali.locator("#currentUserName").textContent())?.includes("امیرعلی"),
    "Display name was not applied after registration.",
  );

  /* حساب دوم روی یک «دستگاه» جدا */
  const yohanna = await signUp(secondContext, {
    username: "yohanna",
    password: "1234",
    name: "یوحنا",
  });

  /* هر دو باید یکدیگر را در فهرست مخاطبان ببینند */
  await amirali.waitForSelector(".contact-item:has-text('یوحنا')", { timeout: 10000 });
  await yohanna.waitForSelector(".contact-item:has-text('امیرعلی')", { timeout: 10000 });
  assert(
    (await amirali.locator(".contact-item").count()) === 1,
    "Only registered accounts should appear in the contact list.",
  );

  /* پیام رفت */
  await amirali.click(".contact-item:has-text('یوحنا')");
  await amirali.fill("#messageInput", "سلام یوحنا، تست شبکه‌ای");
  await amirali.click("#sendButton");
  await yohanna.waitForSelector(".message-row.incoming:has-text('تست شبکه‌ای')", {
    timeout: 10000,
  });

  /* پیام برگشت */
  await yohanna.click(".contact-item:has-text('امیرعلی')");
  await yohanna.fill("#messageInput", "سلام! پیامت رسید.");
  await yohanna.click("#sendButton");
  await amirali.waitForSelector(".message-row.incoming:has-text('پیامت رسید')", {
    timeout: 10000,
  });

  /* ورود دوباره روی یک دستگاه سوم و دیدن تاریخچه */
  const thirdContext = await browser.newContext({
    locale: "fa-IR",
    viewport: { width: 1280, height: 800 },
  });
  const rejoin = await thirdContext.newPage();
  rejoin.on("pageerror", (error) => runtimeErrors.push(`rejoin: ${error.message}`));
  await rejoin.goto(baseUrl, { waitUntil: "networkidle" });
  await rejoin.fill("#username", "amirali");
  await rejoin.fill("#password", "1234");
  await rejoin.click(".login-button");
  await rejoin.waitForURL("**/chat.html", { timeout: 10000 });
  await rejoin.waitForSelector(".message-row:has-text('تست شبکه‌ای')", { timeout: 10000 });

  /* رمز اشتباه نباید وارد شود */
  const fourthContext = await browser.newContext({ locale: "fa-IR", viewport: { width: 1280, height: 800 } });
  const badLogin = await fourthContext.newPage();
  await badLogin.goto(baseUrl, { waitUntil: "networkidle" });
  await badLogin.fill("#username", "amirali");
  await badLogin.fill("#password", "0000");
  await badLogin.click(".login-button");
  await badLogin.waitForSelector(".field.has-error .field-error", { timeout: 10000 });
  assert(badLogin.url().includes("chat.html") === false, "Wrong password must not sign in.");

  assert(runtimeErrors.length === 0, `Runtime errors: ${runtimeErrors.join(" | ")}`);
  console.log("تست دود با موفقیت اجرا شد: ورود، ثبت‌نام، فهرست مخاطبان و پیام‌رسانی بین دستگاه‌ها.");
} finally {
  await browser?.close();
  await server.close();
}
