// frontend/playwright/journey.spec.ts — 여정(오늘의 흐름) E2E
// 문서 §9.1 테스팅 섹션 + 코너케이스(베지어 호버 강조, done 토글, 반응형) 포함.
import { test, expect } from "@playwright/test";

test.beforeEach(async ({ page }) => {
  await page.goto("/journey");
  await expect(page.getByRole("heading", { name: "오늘의 여정" })).toBeVisible();
});

test("헤더: 날짜·날씨 eyebrow + 타이틀", async ({ page }) => {
  await expect(page.locator(".ph-eyebrow")).toContainText("6월 10일 화요일");
  await expect(page.locator(".ph-eyebrow")).toContainText("맑음");
  await expect(page.getByPlaceholder("흐름에서 작업·사람 찾기…")).toBeVisible();
});

test("흐름 패널 라벨: 4단계 · 12개 항목 · 5명 협업", async ({ page }) => {
  const label = page.locator(".jx-label");
  await expect(label).toContainText("오늘의 흐름");
  await expect(label).toContainText("4단계");
  await expect(label).toContainText("12개 항목");
  await expect(label).toContainText("5명 협업");
});

test("4개 컬럼 스테이지 라벨 + 시간", async ({ page }) => {
  const labels = page.locator(".jx-labels .cl");
  await expect(labels).toHaveCount(4);
  await expect(labels.nth(0)).toContainText("아침 준비");
  await expect(labels.nth(1)).toContainText("오전 집중");
  await expect(labels.nth(2)).toContainText("오후 협업");
  await expect(labels.nth(3)).toContainText("마무리 & 내일");
  await expect(labels.nth(0)).toContainText("06:40");
});

test("피플 스택: 핵심 5인", async ({ page }) => {
  // 메일 발신자 제외, 핵심 5명만 (지/현/민/재/수) + '+3' more
  const avs = page.locator(".jx-stack .av");
  await expect(avs).toHaveCount(5);
  await expect(page.locator(".jx-stack .more")).toHaveText("+3");
  await expect(avs.nth(0)).toContainText("지");
  await expect(avs.nth(1)).toContainText("현");
});

test("베지어 커넥터: 8개 .jx-line 경로가 렌더된다", async ({ page }) => {
  // DOM 측정 후 RAF/폰트 로드까지 경로 계산이 끝나길 대기
  await expect.poll(async () => page.locator(".jx-svg .jx-line").count()).toBe(8);
  // svg 는 접근성 트리에서 숨김 + 카드 아래(z-index)
  await expect(page.locator(".jx-svg")).toHaveAttribute("aria-hidden", "true");
});

test("호버 강조: 카드에 올리면 self+이웃 lit, 나머지 mute, 관련 라인 on", async ({ page }) => {
  const report = page.locator(".fcard.task", { hasText: "분기 리포트 초안 마무리" });
  const brief = page.locator(".fcard", { hasText: "아침 브리핑 확인" }); // m-brief → t-report
  const unrelated = page.locator(".fcard.task", { hasText: "온보딩 와이어프레임 피드백 정리" });

  await report.hover();
  await expect(report).toHaveClass(/lit/);
  await expect(brief).toHaveClass(/lit/); // 이웃(들어오는 링크)
  await expect(unrelated).toHaveClass(/mute/); // 비이웃
  // t-report 와 연결된 라인은 .on
  await expect(page.locator(".jx-link.on")).toHaveCount(2); // m-brief>t-report, t-report>k-strat
  await expect(page.locator(".jx-link.off").first()).toBeVisible();

  // 호버 해제 시 강조 초기화
  await page.locator(".jx-label").hover();
  await expect(report).not.toHaveClass(/lit/);
  await expect(page.locator(".jx-link.on")).toHaveCount(0);
});

test("done 토글: 체크 시 카드 done 클래스 + 카운트 감소", async ({ page }) => {
  const card = page.locator(".fcard.task", { hasText: "사용자 인터뷰 5건 정리" });
  await expect(card).not.toHaveClass(/done/);
  // 시작 카운트 3/4 (welcome 만 done) — 컬럼 헤더 카운트 배지(.jx-chead .n)
  const count = page.locator(".jx-chead .n", { hasText: "/4" });
  await expect(count).toHaveText("3/4");

  await card.getByRole("button", { name: "사용자 인터뷰 5건 정리" }).click();
  await expect(card).toHaveClass(/done/);
  await expect(count).toHaveText("2/4");

  // 다시 토글 → 복원
  await card.getByRole("button", { name: "사용자 인터뷰 5건 정리" }).click();
  await expect(card).not.toHaveClass(/done/);
  await expect(count).toHaveText("3/4");
});

test("하단 작업 테이블: 5행 + 상태 칩 + 별 2개 on", async ({ page }) => {
  const rows = page.locator(".jtable tbody tr");
  await expect(rows).toHaveCount(5);
  await expect(page.locator(".jtable .chip.prog").first()).toBeVisible();
  await expect(page.locator(".jtable .chip.review")).toBeVisible();
  await expect(page.locator(".jtable .chip.done")).toBeVisible();
  await expect(page.locator(".jtable .chip.sched")).toBeVisible();
  await expect(page.locator(".jtable .star.on")).toHaveCount(2);
});

test("지표 게이지 2개 + 풋 문구", async ({ page }) => {
  await expect(page.locator(".gauges .gauge")).toHaveCount(2);
  await expect(page.locator(".gauges")).toContainText("딥 워크");
  await expect(page.locator(".gauges")).toContainText("활동 링");
  await expect(page.locator(".gauge-foot")).toContainText("스트레칭");
});

test("힌트 문구 노출", async ({ page }) => {
  await expect(page.locator(".jx-hint")).toContainText("마우스를 올리면");
});

test("반응형: 720px 이하에서 베지어 svg 숨김", async ({ page }) => {
  await expect(page.locator(".jx-svg")).toBeVisible();
  await page.setViewportSize({ width: 700, height: 900 });
  await expect(page.locator(".jx-svg")).toBeHidden();
  await expect(page.locator(".jx-labels")).toBeHidden();
});

test("작업 상태가 라이브 데이터를 반영한다(테이블 ↔ 흐름 일치)", async ({ page }) => {
  // t-welcome 은 done(seed) → 흐름카드/테이블 동기화
  const tableWelcome = page.locator(".jtable tbody tr", { hasText: "신규 입사자 환영" });
  await expect(tableWelcome.locator(".chip.done")).toBeVisible();
});
