// frontend/tests/calendar/views.test.tsx — 뷰 전환 + 집중 블록/카테고리 토글
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { beforeEach, expect, test, vi } from "vitest";
import { CalendarClient } from "@/components/calendar/CalendarClient";
import { DialogProvider } from "@/components/Dialog";
import { calendarApi } from "@/lib/calendar/api";
import type { WeekBundle } from "@/lib/calendar/types";

vi.mock("@/lib/calendar/api");

const BUNDLE: WeekBundle = {
  today: 8,
  today_date: "2026-06-08",
  mode: "demo",
  week: [7, 8, 9, 10, 11, 12, 13],
  weekdays: ["일", "월", "화", "수", "목", "금", "토"],
  calendars: [
    { id: "work", name: "업무", tone: "blue", on: true, count: 1 },
    { id: "health", name: "건강", tone: "coral", on: true, count: 1 },
  ],
  events: [
    {
      id: "w1",
      day: 8,
      date: "2026-06-08",
      start: "11:00",
      end: "11:45",
      title: "디자인 리뷰",
      cal: "work",
      loc: "회의실 B",
      note: "",
      soon: false,
      people: [],
      rrule: "",
      reminders: [],
      attendees: [],
      response_status: "",
      actions: [],
      has_meeting: false,
      meet_label: "",
    },
    {
      id: "h1",
      day: 8,
      date: "2026-06-08",
      start: "20:00",
      end: "20:30",
      title: "스트레칭 & 명상",
      cal: "health",
      loc: "",
      note: "",
      soon: false,
      people: [],
      rrule: "",
      reminders: [],
      attendees: [],
      response_status: "",
      actions: [],
      has_meeting: false,
      meet_label: "",
    },
  ],
  focus_blocks: [
    {
      id: "f3",
      day: 8,
      date: "2026-06-08",
      start: "15:10",
      end: "16:25",
      title: "분기 리포트 초안 마무리",
      type: "deep",
      tag: "딥 워크",
      task_id: null,
      auto: true,
    },
  ],
};

beforeEach(() => {
  localStorage.clear();
  (calendarApi.week as never as ReturnType<typeof vi.fn>).mockResolvedValue(BUNDLE);
});

async function renderReady() {
  const utils = render(<CalendarClient />, { wrapper: DialogProvider });
  // bundle 로딩 완료까지 대기 (주 헤더 표시)
  await screen.findByText("6월 7일 – 13일");
  return utils;
}

test("뷰 세그먼트 전환 week→month→day", async () => {
  await renderReady();
  const weekTab = screen.getByRole("tab", { name: "주" });
  const monthTab = screen.getByRole("tab", { name: "월" });
  const dayTab = screen.getByRole("tab", { name: "일" });

  expect(weekTab).toHaveAttribute("aria-selected", "true");

  fireEvent.click(monthTab);
  await waitFor(() => expect(monthTab).toHaveAttribute("aria-selected", "true"));
  expect(screen.getByRole("heading", { name: "2026년 6월" })).toBeInTheDocument();

  fireEvent.click(dayTab);
  await waitFor(() => expect(dayTab).toHaveAttribute("aria-selected", "true"));
  // 일 뷰 어젠다 헤더
  expect(screen.getByText(/6월 8일 월요일/)).toBeInTheDocument();
});

test("집중 블록 토글 off 시 .fblock 미렌더", async () => {
  const { container } = await renderReady();
  // 주 뷰에 deep focus 블록이 렌더됨
  expect(container.querySelector(".fblock")).toBeTruthy();
  fireEvent.click(screen.getByRole("button", { name: /집중 블록/ }));
  await waitFor(() => expect(container.querySelector(".fblock")).toBeNull());
});

test("카테고리 토글 off 시 해당 cal 이벤트 숨김", async () => {
  await renderReady();
  // 건강 이벤트(스트레칭) 가 주 뷰에 표시됨
  expect(screen.getByText("스트레칭 & 명상")).toBeInTheDocument();
  // 건강 카테고리 토글 off
  fireEvent.click(screen.getByRole("button", { name: /건강/ }));
  await waitFor(() => expect(screen.queryByText("스트레칭 & 명상")).toBeNull());
  // 업무 이벤트는 유지
  expect(screen.getByText("디자인 리뷰")).toBeInTheDocument();
});

test("주 뷰 빈 슬롯 클릭 시 생성 모달 오픈", async () => {
  const { container } = await renderReady();
  // 빈 시간 컬럼(.wk-col) 클릭 → 생성 에디터 오픈
  const col = container.querySelector(".wk-col") as HTMLElement;
  expect(col).toBeTruthy();
  fireEvent.click(col);
  const dialog = await screen.findByRole("dialog", { name: "새 일정" });
  expect(dialog).toBeInTheDocument();
});

test("이벤트 클릭은 슬롯 생성으로 새지 않고 팝오버를 연다", async () => {
  await renderReady();
  // 이벤트 블록 클릭 → 팝오버(편집/삭제 액션) 표시, 생성 모달 아님
  fireEvent.click(screen.getByText("디자인 리뷰"));
  expect(await screen.findByRole("button", { name: /편집/ })).toBeInTheDocument();
  expect(screen.queryByRole("dialog", { name: "새 일정" })).toBeNull();
});
