/* WITNESS · does the wine helper find wine once you ANSWER it?   (re-check of W-094 / STR-1195)
   WHY THIS EXISTS: my earlier walk opened THE CELLAR, read `m2-sommelier-empty` saying "No
   wines on the list right now", and filed STR-1195 saying the helper is blind to a menu that
   sells two wines. That walk never answered the three questions. If that string is the
   PRE-ANSWER placeholder, my finding is false and I have to retract it - so this walk answers
   the quiz properly and reads what comes back.

   The oracle is NOT "no empty element". The drawer mounts q-1, q-2, q-3 AND result all at
   once, so visibility discriminates nothing. The success state must show its OWN evidence:
   the empty element goes 1 -> 0 AND named wines appear.                                    */
import { test, expect } from "@playwright/test";
import { journal, look, arriveAsDiner, DWELL, roleContext, closeRole, PATRON } from "../lib-witness.mjs";
import fs from "node:fs";

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

test("sommelier-answered", async ({ browser }) => {
  const jr = journal("sommelier-answered");
  jr.target({ app: "patron (mosaic_v2)", baseUrl: PATRON, restaurantId: RID, table: TABLE });
  jr.note("**Re-checking my own filed finding STR-1195.** The earlier walk read the helper's "
        + "empty message without answering its three questions. This one answers them.");

  const ctx = await roleContext(browser, jr, "patron");
  const page = await ctx.newPage();
  let verdict = "INCOMPLETE", why = "";
  const wineCalls = [];
  page.on("response", r => { if (/recommendation\/wine/i.test(r.url())) wineCalls.push(`${r.status()} ${r.url().split("?")[0]}`); });

  try {
    await jr.step("PATRON", "I sit down and open THE CELLAR", async id => {
      await arriveAsDiner(page, RID, TABLE, "mosaic_v2");
      const banner = page.locator('[data-testid="m2-sommelier-banner"]').first();
      await expect(banner, "the wine helper should be offered").toBeVisible({ timeout: 25000 });
      await banner.click({ timeout: 20000 });
      await page.waitForTimeout(DWELL);
      const t = await look(page, jr, "patron", id, "cellar just opened");
      const empty0 = await page.locator('[data-testid="m2-sommelier-empty"]').count();
      jr.note(`> **Before I answer anything:** the empty message is present ${empty0} time(s). `
            + "This is the state my earlier walk read and filed a bug about.");
      return `opened. empty-element count before answering = ${empty0}. Screen: ${t.slice(0, 160)}`;
    });

    await jr.step("PATRON", "I answer all three questions", async id => {
      const picked = [];
      for (const q of [1, 2, 3]) {
        /* Take whichever option this question actually offers, rather than assuming which
           option belongs to which question. */
        const opts = page.locator(`[data-testid="m2-sommelier-q-${q}"] [data-testid^="m2-sommelier-option-"]`);
        const n = await opts.count();
        if (!n) { picked.push(`q${q}: no options offered`); continue; }
        const btn = opts.first();
        const tid = await btn.getAttribute("data-testid");
        await btn.click({ timeout: 20000 }).catch(async () => { await btn.evaluate(e => e.click()); });
        await page.waitForTimeout(DWELL);
        picked.push(`q${q} -> ${tid.replace("m2-sommelier-option-", "")}`);
      }
      const t = await look(page, jr, "patron", id, "after answering");
      jr.note(`> **I chose:** ${picked.join(" · ")}`);
      return `${picked.join(" · ")}. Screen: ${t.slice(0, 200)}`;
    });

    await jr.step("PATRON", "The helper now recommends actual wines to me", async id => {
      await page.waitForTimeout(8000);
      const t = await look(page, jr, "patron", id, "the helper's answer");
      const empty = await page.locator('[data-testid="m2-sommelier-empty"]').count();
      const result = (await page.locator('[data-testid="m2-sommelier-result"]').innerText()
                        .catch(() => "")).replace(/\s+/g, " ").trim();
      jr.note(`> **Network:** ${wineCalls.length ? wineCalls.join(" · ") : "no /recommendation/wine call seen"}`);
      jr.note(`> **The result panel says:** ${result.slice(0, 400) || "(nothing)"}`);
      if (empty > 0 && !/\$\d/.test(result))
        throw new Error("even after answering all three questions the helper still shows "
                      + `"No wines on the list right now" and names no wine. Result panel: `
                      + `"${result.slice(0, 200)}"`);
      /* Success needs its OWN positive evidence: the empty message gone AND a priced wine named. */
      expect(empty, "the empty message should be gone once answered").toBe(0);
      expect(result, "the helper should name a priced wine").toMatch(/\$\d/);
      return `empty-element count = ${empty}. It recommends: ${result.slice(0, 260)}`;
    });

    verdict = "HONEST_GREEN";
    why = "Answered, the helper recommends priced wines. The empty message my earlier walk read "
        + "was the PRE-ANSWER placeholder, not an empty cellar — so STR-1195 is my error and must "
        + "be retracted.";
  } catch (e) {
    why = String(e.message || e).split("\n")[0];
  } finally {
    jr.finish(verdict, why);
    await closeRole(ctx, jr, "patron");
  }
  expect(verdict, why).toBe("HONEST_GREEN");
});
