/* WITNESS · can the SECOND diner see the table's order?   (discriminating re-check for W-069)
   A lane reported "diner B is never shown the table's order" from B's Ordered tab reading
   "Nothing sent yet". But that tab defaults to the "(You)" scope, and B never ordered - A did.
   So that reading is consistent with the app being CORRECT, and the claim is unproven.

   The only view that settles it is the ALL scope. This walk: A orders, then B opens the
   Ordered tab and taps `cart-scope-chip-all`, and I read what it says there.

   The oracle is the CONTRAST, not one string: B's own scope may legitimately say "Nothing
   sent yet"; the ALL scope must show the table's placed order. If ALL also says nothing sent
   while A's screen shows it ORDERED, THAT is the defect.                                    */
import { test, expect } from "@playwright/test";
import { journal, look, arriveAsDiner, DWELL, roleContext, closeRole, PATRON } from "../lib-witness.mjs";
import fs from "node:fs";

const RID = JSON.parse(fs.readFileSync("/workspace/uat/runs/wave0/fixtures.json","utf8"))["mosaic_v2-split"];
const TABLE = 9958;                       // a fresh table - the lane's tables carry its own leftovers

test("split-all-scope", async ({ browser }) => {
  const jr = journal("split-all-scope");
  jr.target({ app: "patron (mosaic_v2)", baseUrl: PATRON, restaurantId: RID, table: TABLE });
  jr.note("**Re-checking a claim before I file it.** A lane said the second diner cannot see the "
        + "table's order. Its evidence was B's Ordered tab on the **(You)** scope, where B had "
        + "ordered nothing — so 'Nothing sent yet' may simply be true. This drives the **All** scope.");

  const cA = await roleContext(browser, jr, "patron-a");
  const cB = await roleContext(browser, jr, "patron-b");
  const a = await cA.newPage(), b = await cB.newPage();
  let verdict = "INCOMPLETE", why = "";

  /* The cart control only exists once you have something in the cart, so B must add an item
     first - which is exactly what the lane's B had done. Open by evaluate-click: a full-screen
     m2-dock-scrim intercepts ordinary clicks on this layout. */
  const addOne = async (p) => {
    const add = p.locator('[data-testid^="m2-add-"]').first();
    await expect(add).toBeVisible({ timeout: 25000 });
    await add.evaluate(e => e.click());
    await p.waitForTimeout(DWELL);
  };
  const openOrderedTab = async (p) => {
    const cart = p.locator('[data-testid="m2-view-order"], [data-testid="m2-dock-cart"]').first();
    await expect(cart, "there should be a cart control to open").toHaveCount(1, { timeout: 20000 });
    await cart.evaluate(e => e.click());
    await p.waitForTimeout(DWELL);
    const tab = p.locator('[data-testid="m2-cart-tab-table"]').first();
    await expect(tab, "the cart sheet should offer an Ordered tab").toBeVisible({ timeout: 20000 });
    await tab.evaluate(e => e.click());
    await p.waitForTimeout(3000);
  };
  /* Read the CART SHEET only. The menu shows through behind the sheet, so a page-wide read
     finds dish names and prices and would fake either answer. */
  const sheetText = (p) => p.evaluate(() => {
    const el = document.querySelector('[data-testid="m2-cart-tab-table"]')?.closest("div[class]")?.parentElement
            || document.querySelector('[data-testid="m2-cart-tab-table"]')?.parentElement?.parentElement;
    return (el ? el.innerText : document.body.innerText).replace(/\s+/g, " ").trim();
  });

  try {
    await jr.step("PATRON", "Two of us sit down at the same table", async id => {
      await arriveAsDiner(a, RID, TABLE, "mosaic_v2");
      await arriveAsDiner(b, RID, TABLE, "mosaic_v2");
      const t = await look(b, jr, "patron-b", id, "we are both here");
      return `both arrived. B sees: ${t.slice(0, 130)}`;
    });

    await jr.step("PATRON", "I (diner A) order a drink for the table", async id => {
      const add = a.locator('[data-testid^="m2-add-"]').first();
      await expect(add).toBeVisible({ timeout: 25000 });
      await add.click({ timeout: 25000 });
      await a.waitForTimeout(DWELL);
      await a.locator('[data-testid="m2-view-order"], [data-testid="m2-dock-cart"]').first().click({ timeout: 25000 });
      await a.waitForTimeout(DWELL);
      await a.locator('[data-testid="order-now-btn"]').first().click({ timeout: 25000 });
      await a.waitForTimeout(DWELL);
      await a.locator('[data-testid="m2-cart-tab-table"]').first().evaluate(e => e.click());
      await a.waitForTimeout(3000);
      await look(a, jr, "patron-a", id, "A ordered tab");
      const sheet = await sheetText(a);
      jr.note(`> **A's Ordered tab (sheet only):** ${sheet.slice(0, 260)}`);
      /* Positive evidence, scoped to the sheet: my order must actually appear as ORDERED here,
         or the rest of this walk compares against nothing. */
      expect(sheet, "my own Ordered tab must show my drink as ordered")
        .toMatch(/ordered/i);
      expect(sheet, "and it must not say nothing was sent").not.toMatch(/nothing sent yet/i);
      return `A's Ordered tab reads: ${sheet.slice(0, 220)}`;
    });

    await jr.step("PATRON", "My friend opens Ordered on HER OWN scope", async id => {
      await addOne(b);                 // she needs a cart before a cart control exists
      await openOrderedTab(b);
      await look(b, jr, "patron-b", id, "B ordered tab, HER scope");
      const sheet = await sheetText(b);
      jr.note(`> **B, own scope (sheet only):** ${sheet.slice(0, 260)}`);
      return sheet.slice(0, 220);
    });

    await jr.step("PATRON", "She taps ALL — and this is the view that decides it", async id => {
      const all = b.locator('[data-testid="cart-scope-chip-all"]').first();
      await expect(all, "there should be an All scope to tap").toBeVisible({ timeout: 20000 });
      await all.click({ timeout: 20000 }).catch(async () => { await all.evaluate(e => e.click()); });
      await b.waitForTimeout(DWELL);
      await look(b, jr, "patron-b", id, "B ordered tab, ALL scope");
      const flat = await sheetText(b);
      jr.note(`> **B, ALL scope:** ${flat.slice(0, 260)}`);
      const saysNothing = /nothing sent yet/i.test(flat);
      const showsOrder  = /ordered/i.test(flat);
      if (saysNothing && !showsOrder)
        throw new Error("on the ALL scope my friend's Ordered list still says 'Nothing sent yet' "
                      + "while my screen shows the same drink as ORDERED. She cannot see the "
                      + `table's order. Her screen: ${flat.slice(0, 220)}`);
      return `ALL scope shows: ${flat.slice(0, 240)}`;
    });

    verdict = "HONEST_GREEN";
    why = "On the All scope the second diner DOES see the table's placed order. The lane's claim "
        + "was an artefact of reading the per-person scope, and must not be filed.";
  } catch (e) {
    why = String(e.message || e).split("\n")[0];
  } finally {
    jr.note(`> **Left behind:** a session and one placed order on table ${TABLE}.`);
    jr.finish(verdict, why);
    await closeRole(cA, jr, "patron-a");
    await closeRole(cB, jr, "patron-b");
  }
  expect(verdict, why).toBe("HONEST_GREEN");
});
