/* WITNESS · menu-drink-subcat  (W-042 mosaic_v2-drink-subcat)
 *
 * THE PROMISE: an owner files two drinks under two sub-categories; a diner opening Beverages
 * sees those sub-category dividers and can navigate between them.
 *
 * I drive BOTH halves as a person: first I sit down at the journey's own restaurant and look
 * at Beverages; then I sign in as its owner and try to do the provisioning half — create the
 * drinks, put them on a menu, file the sub-categories — from the owner's own screens.
 * Whatever stops me is the finding.
 */
import { test } from "@playwright/test";
import { journal, look, arriveAsDiner, openCourse, roleContext, deskContext, closeRole,
         signInOwner, account, OWNER, PATRON, DWELL } from "../lib-witness.mjs";
import fs from "node:fs";

const RID = "d4d9a4b3-3c76-5cac-b070-52e77fbba79e";   // Canary Drink Subcategories — dev
const TABLE = 9941;
const CTRL = "28ae37ab-706c-4e20-83d7-52f5d2dff747";  // Canary Mosaic — dev (control)
const CTRL_TABLE = 9942;

const subcatScan = page => page.evaluate(() => {
  const vis = e => e.offsetParent !== null;
  const all = [...document.querySelectorAll("[data-testid]")].filter(vis)
    .map(e => e.getAttribute("data-testid"));
  const sc = all.filter(t => /subcat|group|divider|rail|chip/i.test(t));
  return { subcatish: [...new Set(sc)].sort(),
           tiles: document.querySelectorAll('[data-testid^="m2-tile-"]').length,
           headings: [...document.querySelectorAll("h1,h2,h3,h4")].filter(vis)
             .map(e => (e.innerText||"").replace(/\s+/g," ").trim()).filter(Boolean).slice(0,20) };
});

test("menu-drink-subcat", async ({ browser }) => {
  test.setTimeout(28 * 60_000);
  const jr = journal("menu-drink-subcat");
  jr.target({ patronApp: PATRON, ownerApp: OWNER, restaurantId: RID,
              fixture: "Canary Drink Subcategories — dev", table: TABLE,
              control: { restaurantId: CTRL, fixture: "Canary Mosaic — dev", table: CTRL_TABLE } });
  jr.note("**Where:** Canary Drink Subcategories — dev, table 9941 — the restaurant this "
        + "journey is named after. Canary Mosaic is driven as a control, because it is a "
        + "restaurant that really does have sub-categories.");
  const pc = await roleContext(browser, jr, "patron");
  const oc = await deskContext(browser, jr, "owner");
  const diner = await pc.newPage(), owner = await oc.newPage();
  const state = {};
  let verdict = "INCOMPLETE", why = "";

  try {
    await jr.step("PATRON", "I sit down and open Drinks at the restaurant this journey names",
      async id => {
        await arriveAsDiner(diner, RID, TABLE, "mosaic_v2");
        const t = await look(diner, jr, "patron", id, "Beverages on the drink-subcat fixture");
        state.fixture = await subcatScan(diner);
        jr.note(`> **What Beverages actually shows me:** ${state.fixture.tiles} drink(s), `
              + `sub-category controls: ${state.fixture.subcatish.join(" · ") || "**none**"}`);
        return `${state.fixture.tiles} drink tile(s); sub-category controls: `
             + `${state.fixture.subcatish.join(", ") || "NONE"}. Screen: ${t.slice(0,180)}`;
      });

    await jr.soft("PATRON", "There are sub-category dividers I can navigate between", async id => {
      if (!state.fixture.subcatish.length)
        throw new Error(
          `Beverages here is a single ungrouped list of ${state.fixture.tiles} drink(s). `
        + `There is nothing to navigate between — no divider, no sub-category rail. The two `
        + `drinks and two sub-categories this journey is about are not on the menu when a `
        + `person looks.`);
      return `dividers/rail present: ${state.fixture.subcatish.join(", ")}`;
    });

    await jr.soft("PATRON", "Control: on a restaurant that does have sub-categories, they render",
      async id => {
        await arriveAsDiner(diner, CTRL, CTRL_TABLE, "mosaic_v2");
        const t = await look(diner, jr, "patron", id, "control — Canary Mosaic, Drinks");
        state.control = await subcatScan(diner);
        jr.note(`> **Control (Canary Mosaic, Drinks):** ${state.control.tiles} drink(s), `
              + `sub-category controls: ${state.control.subcatish.join(" · ") || "none"} · `
              + `headings on screen: ${state.control.headings.join(" | ")}`);
        if (!state.control.subcatish.length && !state.control.headings.length)
          throw new Error("even the control restaurant shows no sub-category grouping");
        return `${state.control.tiles} tiles; ${state.control.subcatish.join(", ") || "no subcat testids"}; `
             + `headings: ${state.control.headings.join(" | ")}`;
      });

    await jr.step("OWNER", "I sign in as the owner of this restaurant and open its Menu",
      async id => {
        const a = account("canaryOwner");
        await signInOwner(owner, a.email, a.password, RID);
        await owner.goto(`${OWNER}/owner/menu/?restaurantId=${RID}`, { waitUntil: "domcontentloaded" });
        await owner.waitForTimeout(DWELL * 2);
        let t = await owner.locator("body").innerText();
        if (/Failed to load menu/i.test(t)) {
          const r = owner.getByRole("link", { name: /retry/i })
                    .or(owner.getByRole("button", { name: /retry/i })).first();
          if (await r.count()) { await r.click({ timeout: 15000 }).catch(()=>{}); await owner.waitForTimeout(DWELL * 2); }
        }
        const shot = await look(owner, jr, "owner", id, "my Menu page for this restaurant");
        state.ownerMenuFailed = /Failed to load menu/i.test(shot);
        jr.note(`> **Owner → Menu for this restaurant:** `
              + (state.ownerMenuFailed ? "**\"Failed to load menu — please try again\", and Retry does not help.**"
                                       : "loads."));
        return state.ownerMenuFailed
          ? `"Failed to load menu — please try again." Retry changes nothing. I cannot reach the `
          + `menu builder, so I cannot attach a drink or file a sub-category.`
          : `The menu builder loaded: ${shot.slice(0,200)}`;
      });

    await jr.step("OWNER", "I try the other door — Food Items", async id => {
      await owner.goto(`${OWNER}/owner/food-items/?restaurantId=${RID}`, { waitUntil: "domcontentloaded" });
      await owner.waitForTimeout(DWELL * 2);
      const t = await look(owner, jr, "owner", id, "my Food Items page for this restaurant");
      state.ownerItemsFailed = /Failed to fetch menu-item summaries/i.test(t);
      jr.note(`> **Owner → Food Items for this restaurant:** `
            + (state.ownerItemsFailed ? "**\"Failed to fetch menu-item summaries for "
              + RID + "\" — the whole page is that one line.**" : "loads."));
      return state.ownerItemsFailed
        ? `The page is one red line: "Failed to fetch menu-item summaries". There is no Add Dish `
        + `button, no list, nothing. Both owner doors into this restaurant's menu are shut.`
        : `Food Items loaded: ${t.slice(0,200)}`;
    });

    verdict = "WALKED"; why = "Looked at the diner's Beverages and then tried to do the owner half.";
  } catch (e) {
    verdict = "STOPPED"; why = String(e.message||e).split("\n")[0].slice(0,300);
  } finally {
    fs.writeFileSync(`${jr.dir}/state.json`, JSON.stringify(state, null, 1));
    jr.finish(verdict, why);
    await closeRole(pc, jr, "patron"); await closeRole(oc, jr, "owner");
  }
});
