/* WITNESS · guest table session, driven on TWO ENGINES.

   The question: a diner scans the QR code on an iPhone. Everything on screen works. But did
   the app ever manage to tell the server who they are? Run this with --project=webkit (real
   iOS Safari behaviour, iPhone 14 Pro descriptor) and again with --project=chromium as the
   CONTROL. The walk is identical; only the engine changes. The last step is where they part. */
import { test, expect } from "@playwright/test";
import { journal, look, arriveAsDiner, DWELL, roleContext, closeRole, PATRON, PHONE } from "../lib-witness.mjs";

const RID = "28ae37ab-706c-4e20-83d7-52f5d2dff747";   // Canary Mosaic - a fixture, nobody's meal
const TABLE = 9994;                                    // E2E-safe range

test("guest-session", async ({ browser }) => {
  const engine = test.info().project.name;
  const jr = journal(`guest-session-${engine}`);
  jr.target({ app: "patron (mosaic_v2)", baseUrl: PATRON, restaurantId: RID, table: TABLE, engine });
  jr.note(`**Who:** one diner, alone, on an **iPhone 14 Pro** descriptor driven on the **${engine}** engine.`);
  jr.note("**Where:** the Canary Mosaic fixture, table 9994 — a test table, so nobody's real meal is touched.");
  jr.note("_This walk is deliberately ORDINARY. Nothing a person does here is unusual. The point "
        + "is that the visible journey succeeds on both engines, and the last step is the only "
        + "place they differ — which is exactly why no screenshot-based check would ever catch it._");

  const c = await roleContext(browser, jr, "patron", PHONE);
  const p = await c.newPage();
  const wire = [];
  p.on("response", r => {
    const u = r.url();
    if (/\/auth\/guest|\/diner\/session/.test(u))
      wire.push(`${r.status()} ${r.request().method()} ${u.replace(/^https?:\/\/[^/]+/, "").split("?")[0]}`);
  });

  let verdict = "INCOMPLETE", why = "";
  try {
    await jr.step("PATRON", "I scan the code at my table and a menu appears", async id => {
      const gates = await arriveAsDiner(p, RID, TABLE, "mosaic_v2");
      const t = await look(p, jr, "patron", id, "menu on arrival");
      const dishes = await p.locator('[data-testid^="m2-add-"]').count();
      expect(dishes, "a menu with nothing on it is not a menu").toBeGreaterThan(0);
      return `the app asked me ${gates.length ? gates.join(" and ") : "nothing"}, then showed me `
           + `${dishes} dishes I could add. It reads: ${t.slice(0, 120)}`;
    });

    await jr.step("PATRON", "I add something to my order", async id => {
      await p.locator('[data-testid^="m2-add-"]').first().click({ timeout: 30000 });
      await p.waitForTimeout(DWELL);
      await look(p, jr, "patron", id, "after adding a dish");
      return "the dish went into my order";
    });

    await jr.step("PATRON", "I open my order and send it to the kitchen", async id => {
      await p.locator('[data-testid="m2-view-order"], [data-testid="m2-dock-cart"]').first().click({ timeout: 25000 });
      await p.waitForTimeout(DWELL);
      const btn = p.locator('[data-testid="order-now-btn"]').first();
      expect(await btn.count(), "there was no way to place the order").toBeGreaterThan(0);
      await btn.click({ timeout: 25000 });
      await p.waitForTimeout(DWELL + 7000);
      const t = await look(p, jr, "patron", id, "after placing the order");
      return `I placed the order. The screen reads: ${t.slice(0, 140)}`;
    });

    // THE STEP WHERE THE ENGINES PART. Everything above is identical on both.
    await jr.step("PATRON", "the app has actually identified me to the restaurant", async id => {
      const cookies = (await c.cookies()).map(k => k.name);
      const failed = [...new Set(wire.filter(w => /^[45]\d\d/.test(w)))];
      await look(p, jr, "patron", id, "end of the meal");
      jr.note(`> **Cookies the app is holding:** ${cookies.length ? cookies.join(", ") : "**none at all**"}`);
      jr.note(`> **Session calls the server refused:** ${failed.length ? failed.join(" · ") : "none — all accepted"}`);
      if (failed.length)
        throw new Error(`the restaurant never learned who I am — ${failed.join("; ")}`
          + ` (cookies held: ${cookies.length ? cookies.join(",") : "none"})`);
      return `the app is holding ${cookies.join(", ")} and every session call was accepted`;
    });

    verdict = "WALKED";
    why = "ordered a dish end to end AND the app held a session the restaurant accepted";
  } catch (e) {
    verdict = "STOPPED"; why = String(e.message || e).split("\n")[0].slice(0, 300);
  } finally {
    jr.note("---");
    jr.note(`**Every session call this walk saw, in order:**\n\n\`\`\`\n${wire.join("\n") || "(none)"}\n\`\`\``);
    jr.finish(verdict, why);
    await closeRole(c, jr, "patron");
  }
});
