// frontend/playwright/inbox.spec.ts
// 백엔드를 LLM_PROVIDER=heuristic 로 기동한 상태를 가정(결정성·속도·폴백 배지).
// 캡처는 인박스 시드를 변경하므로 단일 워커 직렬.
import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";
import { resetSeed } from "./fixtures/seed-reset";

test.describe.configure({ mode: "serial" });

// 전체 스위트(직렬)에서 앞선 spec 의 캡처 누적과 무관하게 깨끗한 시드에서 시작.
test.beforeAll(resetSeed);

test("캡처 → 분류 → 좋아요 → 작업 페이지에 등장(연합)", async ({ page }) => {
  await page.goto("/inbox");
  const input = page.getByLabel("인박스에 빠르게 캡처");
  await input.fill("다음 주에 한국 놀러가는 비행기 티켓 사기");
  await input.press("Enter");
  const fresh = page.locator(".sb-cap.fresh").first();
  await expect(fresh.getByText("작업", { exact: true })).toBeVisible();
  await expect(fresh.locator(".r-chip.proj")).toContainText("개인 › 여행 — 한국");
  await expect(fresh.locator(".r-chip.auto")).toContainText("가격 추적 알림 켜둠");
  await fresh.getByRole("button", { name: /좋아요, 그렇게 해줘/ }).click();
  await expect(fresh.locator(".sb-done")).toBeVisible();

  // 작업 페이지(개인 스코프)에서 확인 — 연합 (.first(): 전체 스위트에서 중복 캡처 대비)
  await page.goto("/tasks");
  await page.locator(".tree-row.folder", { hasText: "개인" }).click();
  await expect(
    page.locator(".kcard-title", { hasText: "다음 주에 한국 놀러가는 비행기 티켓 사기" }).first(),
  ).toBeVisible();
});

test("다르게 분류 — 타입 순환 task→event", async ({ page }) => {
  await page.goto("/inbox");
  const input = page.getByLabel("인박스에 빠르게 캡처");
  await input.fill("리포트 회신 보내기");
  await input.press("Enter");
  const fresh = page.locator(".sb-cap.fresh").first();
  await expect(fresh.getByText("작업", { exact: true })).toBeVisible();
  await fresh.getByRole("button", { name: /다르게 분류/ }).click();
  await expect(fresh.getByText("일정", { exact: true })).toBeVisible();
});

const GOLDEN = [
  { raw: "다음 주에 한국 놀러가는 비행기 티켓 사기", type: "작업", proj: "개인 › 여행 — 한국" },
  { raw: "수요일 11시 자전거 수리 맡기기", type: "일정", proj: "개인 캘린더" },
  { raw: "엄마 생신 선물 미리 알아보기", type: "작업", proj: "가족" },
  { raw: "온보딩 환영 화면에 짧은 애니메이션 넣으면 어떨까", type: "아이디어", proj: "아이디어 보드" },
];
for (const g of GOLDEN) {
  test(`골든: "${g.raw}" → ${g.type}`, async ({ page }) => {
    await page.goto("/inbox");
    const input = page.getByLabel("인박스에 빠르게 캡처");
    await input.fill(g.raw);
    await input.press("Enter");
    const fresh = page.locator(".sb-cap.fresh").first();
    await expect(fresh.getByText(g.type, { exact: true })).toBeVisible();
    await expect(fresh.locator(".r-chip.proj")).toContainText(g.proj);
  });
}

test("LLM 폴백 — 규칙 기반(오프라인) 배지", async ({ page }) => {
  await page.goto("/inbox");
  const input = page.getByLabel("인박스에 빠르게 캡처");
  await input.fill("엄마 생신 선물 미리 알아보기");
  await input.press("Enter");
  const fresh = page.locator(".sb-cap.fresh").first();
  await expect(fresh.getByText("작업", { exact: true })).toBeVisible();
  await expect(fresh.getByText("규칙 기반(오프라인)")).toBeVisible();
});

test("음성 스텁 — voice 아이콘 행", async ({ page }) => {
  await page.goto("/inbox");
  await page.getByLabel(/음성으로 캡처/).click();
  await expect(page.locator(".cap-k.voice").first()).toBeVisible();
});

test("a11y — axe 위반 없음(color-contrast 제외)", async ({ page }) => {
  await page.goto("/inbox");
  await expect(page.getByRole("heading", { name: "스마트 인박스", exact: true })).toBeVisible();
  const r = await new AxeBuilder({ page })
    .withTags(["wcag2a", "wcag2aa"])
    .disableRules(["color-contrast"])
    .analyze();
  expect(r.violations).toEqual([]);
});
