/**
 * Self-test bookings read cutover (BOOKINGS_DATABASE=mysql) + live cycle.
 * Uses SUPER_ADMIN (accepted as ADMIN on booking routes).
 */
import fs from "fs";
import path from "path";
import mysql from "mysql2/promise";

function loadEnv() {
  const t = fs.readFileSync(path.join(process.cwd(), ".env"), "utf8");
  for (const line of t.split(/\r?\n/)) {
    const s = line.trim();
    if (!s || s.startsWith("#")) continue;
    const eq = s.indexOf("=");
    if (eq <= 0) continue;
    const k = s.slice(0, eq).trim();
    let v = s.slice(eq + 1).trim();
    if (
      (v.startsWith('"') && v.endsWith('"')) ||
      (v.startsWith("'") && v.endsWith("'"))
    )
      v = v.slice(1, -1);
    process.env[k] = v;
  }
}

async function main() {
  loadEnv();
  const port = process.env.PORT || "4000";
  const base = `http://127.0.0.1:${port}`;
  const results: { name: string; pass: boolean; detail: string }[] = [];
  const check = (name: string, pass: boolean, detail: string) => {
    results.push({ name, pass, detail });
    console.log(`${pass ? "PASS" : "FAIL"}  ${name} — ${detail}`);
  };

  check(
    "env_bookings_mysql",
    (process.env.BOOKINGS_DATABASE || "").toLowerCase() === "mysql",
    `BOOKINGS_DATABASE=${process.env.BOOKINGS_DATABASE}`,
  );

  const login = await fetch(`${base}/api/auth/login`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email: "admin@safarlibya.com", password: "19992000" }),
  });
  const auth: any = await login.json().catch(() => null);
  check("login", login.status === 200 && !!auth?.accessToken, `status=${login.status}`);
  if (!auth?.accessToken) {
    console.log("\nSUMMARY bookings-read: FAIL");
    process.exit(1);
  }
  const headers = {
    Authorization: `Bearer ${auth.accessToken}`,
    "Content-Type": "application/json",
  };

  const list = await fetch(`${base}/api/bookings?as=customer`, { headers });
  const listBody: any = await list.json().catch(() => null);
  check(
    "list_reads_mysql",
    list.status === 200 && listBody?._db === "mysql",
    `status=${list.status} _db=${listBody?._db} count=${listBody?.bookings?.length}`,
  );

  await fetch(`${base}/api/wallet/topups`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      amountLyd: 4000,
      bankName: "مصرف الجمهورية (Demo)",
      reference: `br-${Date.now()}`,
      instantDemo: true,
    }),
  });

  const props = await fetch(`${base}/api/properties?take=10`);
  const propsBody: any = await props.json();
  const property = propsBody?.properties?.[0];
  check("property", !!property?.id, `id=${property?.id}`);

  const checkIn = new Date();
  checkIn.setUTCDate(checkIn.getUTCDate() + 80);
  const checkOut = new Date(checkIn);
  checkOut.setUTCDate(checkOut.getUTCDate() + 2);

  const quote = await fetch(`${base}/api/bookings/quote`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      propertyId: property.id,
      checkIn: checkIn.toISOString().slice(0, 10),
      checkOut: checkOut.toISOString().slice(0, 10),
      guests: 1,
    }),
  });
  const quoteBody: any = await quote.json().catch(() => null);
  const bookingId = quoteBody?.booking?.id;
  check("quote", quote.status === 201 && !!bookingId, `status=${quote.status} err=${quoteBody?.error||""}`);

  const getQuote = await fetch(`${base}/api/bookings/${bookingId}`, { headers });
  const getQuoteBody: any = await getQuote.json().catch(() => null);
  check(
    "get_by_id_mysql",
    getQuote.status === 200 &&
      getQuoteBody?._db === "mysql" &&
      getQuoteBody?.booking?.id === bookingId,
    `status=${getQuote.status} _db=${getQuoteBody?._db}`,
  );

  const pay = await fetch(`${base}/api/bookings/${bookingId}/pay`, {
    method: "POST",
    headers,
    body: JSON.stringify({ useWallet: true }),
  });
  const payBody: any = await pay.json().catch(() => null);
  check("pay", pay.status === 200, `status=${pay.status} booking=${payBody?.booking?.status}`);

  const getAfter = await fetch(`${base}/api/bookings/${bookingId}`, { headers });
  const getAfterBody: any = await getAfter.json().catch(() => null);
  check(
    "read_after_pay_mysql",
    getAfter.status === 200 &&
      getAfterBody?._db === "mysql" &&
      ["CONFIRMED", "WAITING_OWNER"].includes(getAfterBody?.booking?.status),
    `status=${getAfter.status} _db=${getAfterBody?._db} bookingStatus=${getAfterBody?.booking?.status}`,
  );

  const cancel = await fetch(`${base}/api/bookings/${bookingId}/cancel`, {
    method: "POST",
    headers,
  });
  check("cancel", cancel.status === 200 || cancel.status === 409, `status=${cancel.status}`);

  const getCancel = await fetch(`${base}/api/bookings/${bookingId}`, { headers });
  const getCancelBody: any = await getCancel.json().catch(() => null);
  check(
    "read_after_cancel_mysql",
    getCancel.status === 200 &&
      getCancelBody?._db === "mysql" &&
      (getCancelBody?.booking?.status === "CANCELLED" || cancel.status === 409),
    `bookingStatus=${getCancelBody?.booking?.status}`,
  );

  const pool = await mysql.createPool({
    host: process.env.MYSQL_HOST,
    port: Number(process.env.MYSQL_PORT),
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
  });
  const [rows] = await pool.query(`SELECT id, status FROM bookings WHERE id = ?`, [bookingId]);
  const row = (rows as any[])[0];
  check(
    "mysql_row_matches_api",
    !!row && row.status === getCancelBody?.booking?.status,
    `mysql=${row?.status} api=${getCancelBody?.booking?.status}`,
  );
  await pool.end();

  const passed = results.filter((r) => r.pass).length;
  console.log(`\nSUMMARY bookings-read: ${passed}/${results.length} pass`);
  process.exit(passed === results.length ? 0 : 1);
}

main().catch((e) => {
  console.error(e instanceof Error ? e.message : e);
  process.exit(1);
});
