/* WITNESS · owner-modifiers-pairings (W-079)
 *
 * The board reports this canary PARTIAL, failing three steps:
 *   omp-02-tab-labels · omp-03-modifiers-scope · omp-04-pairings-scope
 *
 * What the journey PROMISES an owner (this is the expected value — it comes from the
 * journey's own step list, never from what the screen happens to show):
 *   2  the tab reads "Modifiers", and a "Pairings" tab exists
 *   3  the Modifiers tab explains its scope
 *   4  the Pairings tab explains its scope
 *   5  a pricing switch is visible where it belongs
 *
 * I am not here to decide WHY the canary is red — that is EMP-1's job and I have no source.
 * I am here to answer one question a person can check: can an owner, today, open a dish and
 * see those things? If yes, the red is not telling the truth about the owner's experience.
 *
 * I do NOT flip the pricing switch. Steps 6-8 are about persistence and would mean mutating
 * a canary fixture mid-run, which hands the builder a false red. Not exercised, and the
 * journal says so rather than implying coverage I did not have.
 */
import { test } from "@playwright/test";
import { journal, look, deskContext, closeRole, signInOwner, account, OWNER, DWELL }
  from "../lib-witness.mjs";

const RID  = "28ae37ab-706c-4e20-83d7-52f5d2dff747";   // Canary Mosaic - dev
const ITEM = "bed4a133-4e26-4ef7-981a-c4f52951cae4";   // Canary Caesar Salad
const DEAD = "69f06e43-710d-493b-a553-77d5ccd93bf3";   // the id the canary used to reference

test("owner-modifiers-pairings", async ({ browser }) => {
  const jr = journal("owner-modifiers-pairings");
  jr.target({ app: "owner", url: OWNER, restaurant: "Canary Mosaic - dev", restaurantId: RID,
              item: "Canary Caesar Salad", itemId: ITEM });
  jr.note("_The canary board calls this **PARTIAL**, failing its tab-labels, modifiers-scope "
        + "and pairings-scope steps. This walk asks the only question I can answer from "
        + "outside: **can an owner actually see those things today?**_");

  const ctx  = await deskContext(browser, jr, "owner");
  const page = await ctx.newPage();

  try {
    await jr.step("OWNER", "I can sign in and reach my restaurant", async (id) => {
      const a = account("canaryOwner");
      await signInOwner(page, a.email, a.password, RID);
      const t = await look(page, jr, "owner", id, "signed in");
      return `I am in the owner app. The page reads: ${t.slice(0, 160)}`;
    });

    await jr.step("OWNER", "I can open one of my dishes and edit it", async (id) => {
      await page.goto(`${OWNER}/owner/food-items/?restaurantId=${RID}&itemId=${ITEM}`,
                      { waitUntil: "domcontentloaded" });
      await page.waitForTimeout(DWELL);
      const t = await look(page, jr, "owner", id, "dish editor open");
      const tabs = await page.locator('[data-testid^="tab-"]').allInnerTexts();
      return `The dish editor is open. Along the top I can see ${tabs.length} tabs: `
           + `${tabs.map(x => `"${x.trim()}"`).join(", ")}`;
    });

    // ---- the three steps the board says are failing ------------------------------------
    await jr.step("OWNER", "one of those tabs is called Modifiers, and a Pairings tab exists",
      async (id) => {
        const tabs = (await page.locator('[data-testid^="tab-"]').allInnerTexts())
          .map(x => x.trim());
        const mod  = tabs.find(x => /modifier/i.test(x));
        const pair = tabs.find(x => /pairing/i.test(x));
        await look(page, jr, "owner", id, "tab labels");
        if (!mod || !pair)
          throw new Error(`I cannot see both tabs. What I can see: ${tabs.join(" | ")}`);
        return `Yes — I can read "${mod}" and "${pair}" on screen. `
             + `(The Modifiers tab's testid is tab-groupings, which does not match its label — `
             + `a trap for anyone selecting by name, though a diner or owner never sees it.)`;
      });

    await jr.step("OWNER", "the Modifiers tab tells me what modifiers are for", async (id) => {
      await page.locator('[data-testid="tab-groupings"]').first().click();
      const t = await look(page, jr, "owner", id, "modifiers scope");
      const m = t.match(/Configure the buckets[^.]*\.[^.]*\./i);
      if (!m) throw new Error(`No scope copy under Modifiers. Screen reads: ${t.slice(0, 300)}`);
      return `It explains itself: "${m[0].trim()}"`;
    });

    await jr.step("OWNER", "the Pairings tab tells me what pairings are for", async (id) => {
      await page.locator('[data-testid="tab-pairings"]').first().click();
      const t = await look(page, jr, "owner", id, "pairings scope");
      const m = t.match(/Dishes recommended alongside[^.]*\.[^.]*\./i);
      if (!m) throw new Error(`No scope copy under Pairings. Screen reads: ${t.slice(0, 300)}`);
      return `It explains itself: "${m[0].trim()}"`;
    });

    await jr.step("OWNER", "a pricing switch is visible where pricing applies, and absent "
                         + "where it does not", async (id) => {
      const onPairings = await page.locator('[data-testid*="pricing"]').count();
      await page.locator('[data-testid="tab-groupings"]').first().click();
      await page.waitForTimeout(DWELL);
      const onMods = await page.locator('[data-testid*="pricing"]').count();
      const label = onMods
        ? (await page.locator('[data-testid^="grouping-pricing-label-"]').first()
               .innerText().catch(() => "")).trim()
        : "";
      await look(page, jr, "owner", id, "pricing switch");
      if (!onMods) throw new Error("No pricing control on the Modifiers tab either.");
      return `On Modifiers I can see a pricing switch reading "${label}". On Pairings there `
           + `is none (${onPairings} found) — which matches what Pairings told me: they are `
           + `suggestions, and never change the price.`;
    });

    // ---- the fixture the canary points at -----------------------------------------------
    await jr.soft("OWNER", "the dish the canary refers to still exists", async (id) => {
      await page.goto(`${OWNER}/owner/food-items/?restaurantId=${RID}&itemId=${DEAD}`,
                      { waitUntil: "domcontentloaded" });
      await page.waitForTimeout(DWELL);
      await look(page, jr, "owner", id, "canary fixture item");
      // Assert on the editor's OWN controls, not on prose. My first attempt tested the body
      // text for "not found", found none, and concluded the editor had opened - while the
      // screen was actually the plain food library. A missing error message is not evidence
      // of success; only the drawer's own tabs prove the drawer opened.
      const tabs = await page.locator('[data-testid="tab-groupings"], [data-testid="tab-pairings"]')
                             .count();
      if (!tabs)
        throw new Error(`It does not. Deep-linking to ${DEAD} leaves me on the food library `
                      + `with no editor open - the dish the canary names is gone.`);
      return `It does — the editor opens on it, tabs and all.`;
    });

    jr.finish("WALKED",
      "Every owner-facing thing this journey promises in steps 2-5 is on screen and readable: "
      + "the Modifiers tab, the Pairings tab, both scope explanations, and the pricing switch "
      + "in the one place it belongs. Steps 6-8 are about the switch PERSISTING, which I did "
      + "not exercise - flipping it would mutate a canary fixture mid-run and could hand the "
      + "builder a false red. So this walk covers 5 of 8 steps, and says nothing about the "
      + "other 3.");
  } catch (e) {
    jr.finish("STOPPED", `I could not get further: ${String(e.message || e).split("\n")[0]}`);
    throw e;
  } finally {
    await closeRole(ctx, jr, "owner");
  }
});
