/**
 * Self-test reviews MySQL (reply path + persistence). Create uses Mongo booking eligibility.
 */
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 login(email: string, password: string) {
  const port = process.env.PORT || "4000";
  const res = await fetch(`http://127.0.0.1:${port}/api/auth/login`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password }),
  });
  const body: any = await res.json().catch(() => null);
  if (!res.ok || !body?.accessToken) {
    throw new Error(`login failed status=${res.status} ${JSON.stringify(body)}`);
  }
  return body as { accessToken: string; user: { id: string } };
}

async function main() {
  loadEnv();
  const port = process.env.PORT || "4000";
  const auth = await login("admin@safarlibya.com", "19992000");
  const headers = {
    Authorization: `Bearer ${auth.accessToken}`,
    "Content-Type": "application/json",
  };

  const conn = await mysql.createConnection({
    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 [bookingRows] = await conn.query(
    `SELECT id, property_id, customer_id, owner_id, status
     FROM bookings
     WHERE deleted_at IS NULL AND status IN ('CONFIRMED','COMPLETED')
     LIMIT 5`,
  );
  const bookings = bookingRows as any[];
  if (!bookings.length) throw new Error("no eligible booking in MySQL for review test");

  let booking = bookings[0];
  for (const b of bookings) {
    const [ex] = await conn.query(`SELECT id FROM reviews WHERE booking_id = ? LIMIT 1`, [b.id]);
    if ((ex as any[]).length === 0) {
      booking = b;
      break;
    }
  }

  const marker = `review-selftest-${Date.now()}`;
  const reviewId = `rvw${Date.now().toString(36)}`;
  const now = new Date();

  // Clean any leftover from prior run on same booking if we reuse
  await conn.execute(`DELETE FROM reviews WHERE booking_id = ? AND comment LIKE 'review-selftest-%'`, [
    booking.id,
  ]);

  const [existing] = await conn.query(`SELECT id FROM reviews WHERE booking_id = ? LIMIT 1`, [
    booking.id,
  ]);
  let usedExisting = false;
  let id = reviewId;
  if ((existing as any[]).length) {
    usedExisting = true;
    id = (existing as any[])[0].id;
  } else {
    await conn.execute(
      `INSERT INTO reviews
        (id, booking_id, property_id, author_id, rating, comment, owner_reply, owner_reply_by, created_at, updated_at)
       VALUES (?,?,?,?,?,?,NULL,NULL,?,?)`,
      [reviewId, booking.id, booking.property_id, booking.customer_id, 5, marker, now, now],
    );
  }

  const replyText = `owner-reply-${Date.now()}`;
  const replyRes = await fetch(`http://127.0.0.1:${port}/api/reviews/${id}/reply`, {
    method: "POST",
    headers,
    body: JSON.stringify({ ownerReply: replyText }),
  });
  const replyBody: any = await replyRes.json().catch(() => null);
  const replyOk =
    replyRes.status === 200 &&
    replyBody?._db === "mysql" &&
    String(replyBody?.review?.ownerReply || "").includes("owner-reply-");
  if (!replyOk) {
    console.log(`reply detail status=${replyRes.status} body=${JSON.stringify(replyBody)}`);
  }

  const [after] = await conn.query(`SELECT owner_reply FROM reviews WHERE id = ?`, [id]);
  const persisted = String((after as any[])[0]?.owner_reply || "").includes("owner-reply-");

  // Property detail should include review when properties+reviews on mysql
  const propRes = await fetch(`http://127.0.0.1:${port}/api/properties/${booking.property_id}`);
  const propBody: any = await propRes.json().catch(() => null);
  const listed =
    propRes.status === 200 &&
    Array.isArray(propBody?.property?.reviews) &&
    propBody.property.reviews.some((r: any) => r.id === id || r._id === id);

  if (!usedExisting) {
    await conn.execute(`DELETE FROM reviews WHERE id = ?`, [id]);
  } else {
    // restore reply to previous if we overwrote — leave as is; admin reply is fine for seed data
  }

  await conn.end();

  const results = [
    ["reply", replyOk && persisted],
    ["visible_on_property", listed],
  ] as const;
  for (const [name, pass] of results) console.log(`${pass ? "PASS" : "FAIL"}  ${name}`);
  const ok = results.every(([, p]) => p);
  console.log(`\nSUMMARY reviews: ${ok ? "2/2 pass" : "FAIL"}`);
  process.exit(ok ? 0 : 1);
}

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