/* WITNESS · W-005 dedup-orphan
 *
 * WHAT THE JOURNEY PROMISES (its own 7-step list): when a table is left with a stale,
 * orphaned session alongside a live one, the WAITER's Tables view must show table B as
 * occupied and table A as absent — the duplicate/orphan must not appear as a live table.
 *
 * Six of the seven steps are owner/patron API and websocket work: draining sessions, opening
 * a websocket, seeding a deliberately stale topology, then closing both sessions. Seeding a
 * fake stale session on a live canary fixture is a mutation I will not make — the canary runs
 * this same journey hourly and I would hand the builder a false red.
 *
 * That leaves exactly one step with a screen behind it: step 5, the waiter's Tables view. So
 * that is what I go and look at, with the only staff-capable login this container holds.
 */
import { test } from "@playwright/test";
import { journal, look, roleContext, closeRole, account, WAITER, DWELL } from "../lib-witness.mjs";

const RID = "99e9d621-6941-4acc-8d85-50f15f3a2f2b";   // Canary Kitchen — dev

test("recs-dedup-orphan", async ({ browser }) => {
  const jr = journal("recs-dedup-orphan");
  jr.target({ journey: "W-005 dedup-orphan", app: "waiter", baseUrl: WAITER,
              restaurant: "Canary Kitchen — dev", restaurantId: RID });
  jr.note("**The board calls this PASSED on 7 steps.** Six are API/websocket seeding and "
        + "teardown. I will not seed a fake stale session on a live canary fixture — that is a "
        + "mutation, and the canary runs this journey hourly. The one step with a screen is "
        + "step 5: *UI: Waiter Tables — B occupied, A absent.*");

  const ctx = await roleContext(browser, jr, "waiter", "Desktop Chrome");
  const w = await ctx.newPage();
  let verdict = "INCOMPLETE", why = "";

  try {
    await jr.step("WAITER", "I sign in as staff at this restaurant", async id => {
      const a = account("canaryOwner");
      let landed = "";
      for (let attempt = 1; attempt <= 3; attempt++) {
        await w.goto(`${WAITER}/owner/auth/login/`, { waitUntil: "domcontentloaded" });
        await w.waitForTimeout(DWELL);
        const em = w.locator('[data-testid="login-email"], input[type=email]').first();
        if (await em.count()) {
          await em.fill(a.email);
          await w.locator('[data-testid="login-password"], input[type=password]').first().fill(a.password);
          await w.locator('[data-testid="login-submit"]').first().click({ timeout: 25000 }).catch(()=>{});
          await w.waitForTimeout(DWELL + 18000);
        }
        landed = w.url();
        const err = (await w.locator('[data-testid="login-error"], [role=alert]').first().innerText().catch(()=>"")).replace(/\s+/g," ");
        if (err) jr.note(`> **Attempt ${attempt}: the login form says** "${err.slice(0,160)}"`);
        if (!/auth\/login/.test(landed)) break;
        await w.waitForTimeout(8000);
      }
      const t = await look(w, jr, "waiter", id, "signed in to the waiter app");
      jr.note("> _The only staff-capable account in this container is the canary restaurants' "
            + "OWNER. There is no waiter account for any canary restaurant here._");
      if (/auth\/login/.test(landed))
        throw new Error(`the sign-in never completed — after two attempts I am still on the login `
                      + `page (${landed}). That is a harness problem of mine, not a product finding.`);
      return `landed on ${landed}. Screen: ${t.slice(0,240)}`;
    });

    await jr.step("WAITER", "I open the Tables view and read which tables are occupied", async id => {
      const tab = w.locator('[data-testid="tab-tables"]').first()
                    .or(w.getByRole("button", { name: /^tables$/i }).first());
      if (await tab.count()) { await tab.click({ timeout: 20000 }).catch(async()=>{ await tab.evaluate(e=>e.click()); }); }
      await w.waitForTimeout(DWELL + 3000);
      const t = await look(w, jr, "waiter", id, "tables view");
      const rows = await w.locator('[data-testid*="table-"], table tbody tr').count().catch(()=>0);
      const none = /no tables assigned/i.test(t);
      jr.note(`> **The Tables view reads:** ${t.slice(0,320)}`);
      if (none || rows === 0)
        throw new Error("this account is not assigned to any table, so the Tables view lists "
                      + "nothing at all — I cannot see whether an orphaned session would show up "
                      + `as an extra occupied table. The screen says: "${(t.match(/No tables[^.]*/i)||[t.slice(0,90)])[0]}"`);
      return `${rows} table row(s) visible. ${t.slice(0,260)}`;
    });

    verdict = "WALKED"; why = "read the waiter Tables view";
  } catch (e) {
    verdict = "STOPPED"; why = String(e.message||e).split("\n")[0].slice(0,320);
  } finally {
    jr.note("**Cleanup:** none — I signed in and looked; I seeded nothing and closed nothing.");
    jr.finish(verdict, why);
    await closeRole(ctx, jr, "waiter");
  }
});
