/* WITNESS · owner-bulk-actions  (W-078 owner-menu-bulk-actions)
 *
 * WHY THIS WALK EXISTS
 * --------------------
 * The food library offers a bulk-actions panel. The App-Doc — the owner app's own manual and,
 * per project rule, its Book of Truth — is reported to have no entry for it at all, while the
 * panel offers **Delete** applied to every selected dish at once. This walk drives the panel
 * as an owner and records exactly what it offers, so the gap can be stated in the panel's own
 * terms rather than from a description of it.
 *
 * ⛔ NO MUTATION, AND THE ONE CONTROL THAT MATTERS IS `bulk-apply`.
 * I select rows, open the panel, and read every mode. I never press `bulk-apply` and never
 * press Delete. Selection is client-side and is cleared before I leave.
 *
 * THE ORACLE IS THE PANEL'S OWN CONTENT.
 * I do not assert "no error appeared". I assert the panel renders, name every mode it offers,
 * and read the commit button's own label. If the panel does not open, the walk STOPS.
 */
import { test } from "@playwright/test";
import { journal, look, signInOwner, account, closeRole, deskContext, OWNER, DWELL }
  from "../lib-witness.mjs";
import fs from "node:fs";

const RID = JSON.parse(fs.readFileSync("/workspace/uat/runs/wave0/fixtures.json","utf8"))["canary-mosaic"];

test("owner-bulk-actions", async ({ browser }) => {
  const jr = journal("owner-bulk-actions");
  jr.target({ app: "owner", url: OWNER, restaurantId: RID, fixture: "canary-mosaic",
              route: "/owner/food-items/" });
  jr.note("_What can an owner do to every dish at once, and does the manual say so?_");
  jr.note("**No mutation:** rows are selected client-side and cleared again. `bulk-apply` is "
        + "read, never pressed.");

  const ctx = await deskContext(browser, jr, "owner");
  const page = await ctx.newPage();
  let verdict = "INCOMPLETE", why = "", modes = [];

  try {
    await jr.step("OWNER", "I open my food library", async id => {
      const a = account("canaryOwner");
      await signInOwner(page, a.email, a.password, RID);
      await page.goto(`${OWNER}/owner/food-items/?restaurantId=${RID}`,
                      { waitUntil: "domcontentloaded" });
      await page.waitForTimeout(DWELL * 2);
      const t = await look(page, jr, "owner", id, "the food library");
      const rows = await page.locator('[data-testid^="food-library-visibility-toggle-"]').count();
      if (!rows) throw new Error(`No dishes listed. Screen: ${t.slice(0,200)}`);
      return `${rows} dish(es) listed.`;
    });

    await jr.step("OWNER", "I select everything with one click", async id => {
      const all = page.locator('[data-testid="food-library-table-select-all"]').first();
      if (!(await all.count())) throw new Error("There is no select-all control on this table.");
      await all.evaluate(el => el.click());
      await page.waitForTimeout(2500);
      const t = await look(page, jr, "owner", id, "everything selected");
      const count = await page.locator('[data-testid="food-library-table-bulk-count"]').first()
                              .innerText().catch(() => "");
      if (!count.trim())
        throw new Error(`Selecting everything produced no selection bar. Screen: ${t.slice(0,200)}`);
      jr.note(`> **One click selects:** \`${count.trim()}\``);
      return `The bar reads "${count.trim()}".`;
    });

    await jr.step("OWNER", "I open the bulk actions panel and read what it offers",
      async id => {
        await page.locator('[data-testid="food-library-table-bulk-action"]').first()
                  .evaluate(el => el.click());
        await page.waitForTimeout(DWELL);
        const t = await look(page, jr, "owner", id, "the bulk panel");
        if (!(await page.locator('[data-testid="bulk-actions-panel"]').count()))
          throw new Error(`The bulk panel did not open. Screen: ${t.slice(0,220)}`);
        modes = await page.evaluate(() =>
          [...document.querySelectorAll('[data-testid^="bulk-tab-"]')]
            .map(e => `${e.getAttribute("data-testid")}="${(e.innerText||"").replace(/\s+/g," ").trim()}"`));
        const apply = await page.locator('[data-testid="bulk-apply"]').first()
                                .innerText().catch(() => "");
        jr.note(`> **${modes.length} things I can do to every dish at once:**\n>\n> - `
              + modes.join("\n> - "));
        jr.note(`> **The button that commits it reads:** \`${apply.replace(/\s+/g," ").trim()}\``);
        if (!modes.length) throw new Error("The panel opened but offers no modes I can name.");
        return `${modes.length} modes, committed by a button reading `
             + `"${apply.replace(/\s+/g," ").trim()}".`;
      });

    await jr.step("OWNER", "One of them is Delete — I look at it without pressing anything",
      async id => {
        const del = page.locator('[data-testid="bulk-tab-delete"]').first();
        if (!(await del.count()))
          return `There is no bulk Delete mode. The modes are: ${modes.join(", ")}`;
        await del.evaluate(el => el.click());
        await page.waitForTimeout(2500);
        const t = await look(page, jr, "owner", id, "bulk delete, not pressed");
        const apply = await page.locator('[data-testid="bulk-apply"]').first()
                                .innerText().catch(() => "");
        const warns = /cannot be undone|permanent|are you sure|confirm/i.test(t);
        jr.note(`> **In Delete mode the commit button reads:** \`${apply.replace(/\s+/g," ").trim()}\``
              + ` · **the panel warns this is irreversible:** ${warns}`);
        return `Delete is one click plus a commit button reading `
             + `"${apply.replace(/\s+/g," ").trim()}". I did not press it. The panel `
             + `${warns ? "does" : "does NOT"} warn that this cannot be undone.`;
      });

    await jr.step("OWNER", "I put everything back the way I found it", async id => {
      await page.locator('[data-testid="bulk-cancel"], [data-testid="bulk-panel-close"]').first()
                .evaluate(el => el.click()).catch(() => {});
      await page.waitForTimeout(2000);
      await page.locator('[data-testid="food-library-table-bulk-clear"]').first()
                .evaluate(el => el.click()).catch(() => {});
      await page.waitForTimeout(2000);
      const t = await look(page, jr, "owner", id, "selection cleared");
      const still = await page.locator('[data-testid="food-library-table-bulk-count"]').count();
      return still
        ? `A selection bar is still showing — worth noting, but nothing was applied.`
        : `Selection cleared, panel closed, nothing applied. ${t.slice(0,120)}`;
    });

    await jr.step("OWNER", "Does the manual tell an owner any of this?", async id => {
      await page.goto(`${OWNER}/owner/app-doc/?restaurantId=${RID}`, { waitUntil: "domcontentloaded" });
      await page.waitForTimeout(DWELL * 2);
      /* Open every tab and every collapsible, or a "not documented" reading is just an
         unopened accordion. */
      await page.evaluate(() => {
        document.querySelectorAll("details").forEach(d => d.open = true);
        document.querySelectorAll('[data-testid^="app-doc-tab-"]').forEach(b => b.click());
      });
      await page.waitForTimeout(3000);
      await page.evaluate(() => document.querySelectorAll("details").forEach(d => d.open = true));
      await page.waitForTimeout(1500);
      const t = await look(page, jr, "owner", id, "the owner's manual");
      const body = await page.evaluate(() => document.body.innerText);
      const hits = ["bulk", "select all", "at once", "delete"].map(w =>
        `${w}: ${(body.toLowerCase().match(new RegExp(w, "g")) || []).length}`);
      jr.note(`> **Mentions in the whole rendered manual:** ${hits.join(" · ")} `
            + `(manual is ${body.length} chars, all tabs clicked, all collapsibles forced open)`);
      const bulk = (body.toLowerCase().match(/bulk/g) || []).length;
      if (bulk) return `The manual mentions "bulk" ${bulk} time(s).`;
      return `The manual never uses the word "bulk" — not once in ${body.length} characters, `
           + `with every tab opened and every collapsible expanded. So the panel that can `
           + `delete every dish in one action is not in the owner's own Book of Truth.`;
    });

    verdict = "WALKED"; why = "Read the bulk panel and checked the manual against it.";
  } catch (e) {
    verdict = "STOPPED"; why = String(e.message||e).split("\n")[0].slice(0,300); throw e;
  } finally { jr.finish(verdict, why); await closeRole(ctx, jr, "owner"); }
});
