/* WITNESS · mosaic_v2-split-combos (W-070) — QRATE-UAT-1
 *
 * WHY THIS EXISTS: parked as blocked, wrongly. Only the FIRST diner ever sent an order, so
 * the app correctly had nothing to split - and I wrote that up as the app offering nothing.
 * `placeOwnOrder` now proves each diner's order reached the table ledger before anything
 * downstream depends on it.
 *
 * THE QUESTION: two people ate together. Can they divide the bill between them?
 *
 * NOT PRESSED: no payment control is ever touched. These fixtures are live Stripe merchants
 * on dev, so this walks up to the split choice and stops there.
 */
import { test } from "@playwright/test";
import { journal, look, roleContext, closeRole, DWELL } from "../lib-witness.mjs";
import { arrive, tap, whoIsHere, settleControls, openSheet, placeOwnOrder } from "./split-lib.mjs";
import fs from "node:fs";

const F = JSON.parse(fs.readFileSync("/workspace/uat/runs/wave0/fixtures.json", "utf8"));
const RID = F["mosaic_v2-split-combos"] || F["mosaic_v2-split"];
const TABLE = 9973;

test("mosaic_v2-split-combos", async ({ browser }) => {
  const jr = journal("mosaic_v2-split-combos");
  jr.target({ app: "patron x2", restaurantId: RID, table: TABLE, fixture: "Canary Mosaic V2 — dev" });
  jr.note("_Two diners, two real orders, then the bill. I never press a payment control - these "
        + "fixtures are live Stripe merchants on dev - so this walks up to the split choice and stops._");

  const c1 = await roleContext(browser, jr, "diner-1");
  const p1 = await c1.newPage();
  const c2 = await roleContext(browser, jr, "diner-2");
  const p2 = await c2.newPage();
  let verdict = "INCOMPLETE", why = "";
  const rec = {};

  try {
    await jr.step("PATRON", "Both diners sit down and each orders their own food", async id => {
      await arrive(p1, RID, TABLE);
      rec.o1 = await placeOwnOrder(p1, "Diner one");
      await look(p1, jr, "diner-1", id, "diner one has ordered");
      await arrive(p2, RID, TABLE);
      rec.o2 = await placeOwnOrder(p2, "Diner two");
      await look(p2, jr, "diner-2", id, "diner two has ordered");
      rec.who = await whoIsHere(p2);
      jr.note(`> **At the table:** ${rec.who.map(w => w.text).join(" · ") || "no names"}`);
      return `Two real orders on this table. Diner one: "${rec.o1.badge}". Diner two: "${rec.o2.badge}".`;
    });

    await jr.step("PATRON", "One of them asks for the bill", async id => {
      const opened = await openSheet(p2);
      await p2.waitForTimeout(DWELL);
      const sheet = await p2.evaluate(() => {
        const s = document.querySelector('[data-testid="cart-sheet"]');
        return { present: !!s,
                 ids: [...document.querySelectorAll("[data-testid]")]
                   .map(e => e.getAttribute("data-testid"))
                   .filter(x => /cart|sheet|order|dock|check|bill/i.test(x)).slice(0, 25) };
      });
      jr.note(`> **Order sheet open?** ${sheet.present ? "yes" : "NO"} · \`${sheet.ids.join("`, `")}\``);
      if (!sheet.present)
        throw new Error(`Could not open the order sheet (openSheet=${opened}) - my harness, not the `
          + `product. Present: ${sheet.ids.join(", ") || "none"}.`);
      // `check-please` / `m2-check-please` do not exist in the DOM. The real control is
      // `service-bubble-ready_for_bill`, inside the SERVICE BUBBLE, opened by a custom event -
      // the same miss that parked mosaic_v2-cover-someone. Open the bubble, then press it.
      await p2.evaluate(() => window.dispatchEvent(new CustomEvent("qrate:open-service-bubble")));
      await p2.waitForTimeout(DWELL);
      const check = p2.locator('[data-testid*="ready_for_bill"], [data-testid*="check-please"], '
                             + '[data-testid*="settlement"]').first();
      if (!(await check.count()))
        throw new Error(`The order sheet is open but offers no way to ask for the bill.`);
      await tap(p2, check);
      await p2.waitForTimeout(DWELL);
      const t = await look(p2, jr, "diner-2", id, "asked for the bill");
      rec.settle = await settleControls(p2);
      jr.note(`> **What she is offered once the bill is asked for:** \`${rec.settle.join("`, `")}\``);
      if (!rec.settle.length)
        throw new Error(`Asked for the bill and was offered nothing at all - no split, no cover, `
          + `no pay. Both diners have ordered on this table. Screen: ${t.slice(0, 200)}`);
      return `Offered: ${rec.settle.join(", ")}.`;
    });

    await jr.step("PATRON", "She looks for a way to divide it between the two of them", async id => {
      const split = p2.locator('[data-testid*="split"]').first();
      if (!(await split.count()))
        throw new Error(`No way to split is offered, though two people have each ordered. `
          + `Everything offered: ${rec.settle.join(", ")}.`);
      await tap(p2, split);
      await p2.waitForTimeout(DWELL);
      const t = await look(p2, jr, "diner-2", id, "split choices");
      const ways = await p2.evaluate(() => [...document.querySelectorAll('[data-testid*="split"]')]
        .map(e => ({ id: e.getAttribute("data-testid"),
                     text: (e.innerText || "").replace(/\s+/g, " ").trim().slice(0, 60) })));
      rec.ways = ways;
      jr.note(`> **Ways to split she is offered:** ${ways.map(w => w.text || w.id).join(" · ") || "NONE"}`);
      if (ways.length < 2)
        throw new Error(`The split screen opened but offers ${ways.length} option(s), so there is no `
          + `combination to choose between. Screen: ${t.slice(0, 200)}`);
      return `${ways.length} ways to split: ${ways.map(w => w.text || w.id).filter(Boolean).join(", ")}. `
           + `I stop here - pressing a payment control on a live Stripe fixture is not mine to do.`;
    });

    verdict = "PARTIAL_GREEN";
    why = "Both diners ordered for real, the bill was asked for, and split options were offered. "
        + "I stop short of paying: these fixtures are live Stripe merchants.";
  } catch (e) {
    why = e.message; verdict = "HONEST_RED";
  } finally {
    for (const [pg, ctx, name] of [[p1, c1, "diner-1"], [p2, c2, "diner-2"]]) {
      try {
        await openSheet(pg);
        const c = pg.locator('[data-testid^="cancel-item-"]').first();
        if (await c.count()) { await c.click({ timeout: 6000 }).catch(() => {}); await pg.waitForTimeout(2000); }
      } catch {}
      await closeRole(ctx, jr, name);
    }
    jr.note("> **Cleanup:** each diner cancelled their own dish where the control was still offered.");
    jr.finish(verdict, why);
  }
});
