/* WITNESS · W-083 pos-modifier-link — "the POS-import staging queue folds a staged Clover
 *                                       group into one modifier, links it across every dish,
 *                                       a diner sees it, and unlinking drops the routing"
 *
 * WHAT THE JOURNEY PROMISES (5 steps, all CANARY/PATRON — no manual owner click-through was
 * ever the point; the canary automation is meant to assert these against a REAL staged
 * import):
 *   1  the folded queue shows the staged Clover group
 *   2  linking fans it out across every dish
 *   3  a diner sees the linked option
 *   4  the queue reports it paired
 *   5  unlinking drops the ROUTING, keeps the menu
 *
 * PRIOR BLOCKER WAS STALE: the ledger's own text said "I have no owner Cognito credentials in
 * this UAT container" - that was true before the 2026-09-05 EMP-1 credential pack; canaryOwner
 * now exists and DOES reach the owner app fine (confirmed this run). The real blocker, found by
 * actually looking: Canary Kitchen - dev has NO POS system connected at all
 * (`/owner/settings/pos/` reads `pos-not-connected`) - so there is no staged Clover import, no
 * folded queue, nothing for steps 1/2/4/5 to be true or false about. Connecting a real POS
 * integration needs live Clover/Toast/Square credentials this container does not hold and is
 * not mine to provision on a shared hourly canary fixture regardless.
 */
import { test, expect } from "@playwright/test";
import fs from "node:fs";
import { journal, look, account, DWELL, OWNER, PATRON, deskContext, roleContext, closeRole,
         arriveAsDiner, signInOwner } from "../lib-witness.mjs";

const RID = "99e9d621-6941-4acc-8d85-50f15f3a2f2b"; // Canary Kitchen - dev
const DINER_RID = "28ae37ab-706c-4e20-83d7-52f5d2dff747"; // Canary Mosaic V2 Dining
const TABLE = 9949;

test("pos-modifier-link", async ({ browser }) => {
  const jr = journal("pos-modifier-link");
  jr.target({ app: "owner + patron", baseUrl: OWNER, restaurantId: RID, table: TABLE });
  jr.note("**Who:** the canary owner on a laptop, checking the POS-import queue; a diner on a "
        + "phone, checking whether anything is offered as a linked modifier.");

  const cO = await deskContext(browser, jr, "owner");
  const o = await cO.newPage();
  const ev = {};
  let verdict = "INCOMPLETE", why = "";

  try {
    await jr.step("OWNER", "I sign in as the canary owner", async id => {
      const a = account("canaryOwner");
      await signInOwner(o, a.email, a.password, RID);
      return (await look(o, jr, "owner", id, "signed in")).slice(0, 160);
    });

    await jr.step("CANARY", "the folded queue shows a staged Clover group waiting to be linked",
      async id => {
        await o.goto(`${OWNER}/owner/settings/pos/?restaurantId=${RID}`, { waitUntil: "domcontentloaded" });
        await o.waitForTimeout(DWELL + 2000);
        const notConnected = await o.locator('[data-testid="pos-not-connected"]').count();
        const t = await look(o, jr, "owner", id, "pos settings");
        ev.posConnected = !notConnected;
        if (notConnected) {
          // Look, don't leap: is "Get started" just informational, or does it need real creds?
          const btn = o.locator('[data-testid="pos-get-started-btn"]').first();
          if (await btn.count()) {
            await btn.click({ timeout: 15000 }).catch(() => {});
            await o.waitForTimeout(DWELL);
            const t2 = await look(o, jr, "owner", `${id}-getstarted`, "pos get-started");
            ev.getStartedScreen = t2.slice(0, 300);
          }
          throw new Error(`No POS system is connected on Canary Kitchen at all - the page reads `
                         + `"pos-not-connected". There is no staged Clover import, so there is no `
                         + `folded queue for step 1 to be true or false about. Screen: ${t.slice(0, 240)}`);
        }
        return `POS is connected. Screen: ${t.slice(0, 220)}`;
      });
  } catch (e) {
    verdict = "DEFERRED"; why = String(e.message || e).split("\n")[0].slice(0, 500);
  } finally {
    await closeRole(cO, jr, "owner");
  }

  // ---- the diner half: is there anything on the CANARY MOSAIC menu offered as a linked
  // modifier right now, regardless of POS provenance? Answers step 3 on its own merits. -------
  const cP = await roleContext(browser, jr, "diner");
  const p = await cP.newPage();
  try {
    await jr.soft("PATRON", "a diner sees a dish offering a linked modifier with options",
      async id => {
        await arriveAsDiner(p, DINER_RID, TABLE, "mosaic_v2");
        const found = [];
        for (const course of ["Beverages", "Appetizers", "Entrees", "Desserts"]) {
          const b = p.locator(`[data-testid="m2-section-${course}"]`).first();
          if (!(await b.count())) continue;
          await b.evaluate(el => el.click());
          await p.waitForTimeout(2500);
          const n = await p.locator('[data-testid^="m2-tile-"]').count();
          for (let i = 0; i < Math.min(n, 4); i++) {
            await arriveAsDiner(p, DINER_RID, TABLE, "mosaic_v2");
            await p.locator(`[data-testid="m2-section-${course}"]`).first().evaluate(el => el.click());
            await p.waitForTimeout(2000);
            await p.locator('[data-testid^="m2-tile-"]').nth(i).click({ timeout: 15000 }).catch(() => {});
            await p.waitForTimeout(2500);
            const s = p.locator('[data-testid="m2-composition"]');
            if (!(await s.count())) continue;
            const ids = [...new Set(await s.evaluate(el =>
              [...el.querySelectorAll("[data-testid]")].map(e => e.getAttribute("data-testid"))))];
            const optionish = ids.filter(x => /group|option|modifier|member|choice/i.test(x));
            if (optionish.length) found.push(`${course}#${i}: ${optionish.join(",")}`);
          }
        }
        ev.dinerLinkedModifiers = found;
        await look(p, jr, "diner", id, "dish sheet sweep");
        jr.note(`> **Dishes offering any modifier/option on Canary Mosaic:** `
              + (found.join(" · ") || "none found in the courses swept"));
        if (!found.length)
          throw new Error("Swept Beverages/Appetizers/Entrees/Desserts on Canary Mosaic - no "
                         + "dish offered a modifier or option group. Nothing here answers step 3.");
        return found.join(" · ");
      });
  } finally {
    fs.writeFileSync(`${jr.dir}/evidence.json`, JSON.stringify(ev, null, 1));
    jr.finish(verdict, why);
    await closeRole(cP, jr, "diner");
  }

  expect(verdict, why).not.toBe("BOGUS_NEVER_HIT");
});
