// frontend/components/calendar/CalendarClient.tsx — 일정 페이지 오케스트레이터 (Topbar 제외)
"use client";
import { useEffect, useRef, useState, type MouseEvent } from "react";
import { Icon } from "@/components/Icon";
import { calendarApi } from "@/lib/calendar/api";
import { loadLS, saveLS } from "@/lib/calendar/store";
import type { CalEvent, WeekBundle } from "@/lib/calendar/types";
import { MiniCal } from "./MiniCal";
import { CalToggleList } from "./CalToggleList";
import { WeekView } from "./WeekView";
import { MonthView } from "./MonthView";
import { DayView } from "./DayView";
import { EvPopover } from "./EvPopover";
import { MeetDrawer } from "./MeetDrawer";

const VIEWS = [
  { id: "week", label: "주" },
  { id: "month", label: "월" },
  { id: "day", label: "일" },
];

function countByDay(events: CalEvent[]): Record<number, number> {
  const m: Record<number, number> = {};
  events.forEach((e) => {
    m[e.day] = (m[e.day] || 0) + 1;
  });
  return m;
}

function CalendarSkeleton() {
  return (
    <div className="calpage">
      <div className="twork" aria-busy="true">
        <aside className="subnav">
          <div className="sn-title">일정</div>
          <div className="cal-skel-col">
            {[0, 1, 2, 3].map((i) => (
              <div key={i} className="cal-skel" style={{ height: 34 }} />
            ))}
          </div>
        </aside>
        <main className="cmain">
          <div className="cal-skel" style={{ height: 40, width: 240, marginBottom: 16 }} />
          <div className="cpanel">
            <div className="cal-skel" style={{ height: 420 }} />
          </div>
        </main>
      </div>
    </div>
  );
}

export function CalendarClient() {
  const [bundle, setBundle] = useState<WeekBundle | null>(null);
  const [err, setErr] = useState(false);
  const [view, setView] = useState<string>("week");
  const [selDay, setSelDay] = useState<number>(8);
  const [calOn, setCalOn] = useState<Record<string, boolean>>({});
  const [focusOn, setFocusOn] = useState<boolean>(true);
  const [hydrated, setHydrated] = useState(false);
  const [pop, setPop] = useState<{ ev: CalEvent; x: number; y: number } | null>(null);
  const [meetEv, setMeetEv] = useState<CalEvent | null>(null);
  const shellRef = useRef<HTMLDivElement>(null);

  // 클라이언트에서만 localStorage 복원 (SSR 안정)
  useEffect(() => {
    setView(loadLS("view", "week"));
    setSelDay(loadLS("selDay", 8));
    setCalOn(loadLS<Record<string, boolean>>("calOn", {}));
    setFocusOn(loadLS("focusOn", true));
    setHydrated(true);
  }, []);

  const load = () => {
    setErr(false);
    calendarApi
      .week()
      .then((b) => {
        setBundle(b);
        setCalOn((cur) =>
          Object.keys(cur).length ? cur : Object.fromEntries(b.calendars.map((c) => [c.id, c.on])),
        );
      })
      .catch(() => setErr(true));
  };
  useEffect(load, []);

  useEffect(() => {
    if (hydrated) saveLS("view", view);
  }, [view, hydrated]);
  useEffect(() => {
    if (hydrated) saveLS("selDay", selDay);
  }, [selDay, hydrated]);
  useEffect(() => {
    if (hydrated) saveLS("calOn", calOn);
  }, [calOn, hydrated]);
  useEffect(() => {
    if (hydrated) saveLS("focusOn", focusOn);
  }, [focusOn, hydrated]);

  useEffect(() => {
    const el = shellRef.current;
    const id = requestAnimationFrame(() => el && el.classList.add("entered"));
    return () => cancelAnimationFrame(id);
  }, [bundle]);

  if (err && !bundle) {
    return (
      <div className="calpage">
        <div className="cal-error" role="alert">
          <Icon name="x" /> 일정을 불러오지 못했어요
          <button onClick={load}>다시 시도</button>
        </div>
      </div>
    );
  }

  if (!bundle) return <CalendarSkeleton />;

  const calMap = Object.fromEntries(bundle.calendars.map((c) => [c.id, c]));
  const events = bundle.events.filter((e) => calOn[e.cal] !== false);
  const focusBlocks = focusOn ? bundle.focus_blocks : [];
  const openEv = (ev: CalEvent, e: MouseEvent) =>
    setPop({ ev, x: e.clientX + 8, y: e.clientY + 8 });
  const openMeet = (ev: CalEvent) => {
    setPop(null);
    setMeetEv(ev);
  };
  const title =
    view === "month" ? "2026년 6월" : view === "day" ? `6월 ${selDay}일` : "6월 7일 – 13일";

  return (
    <div className="calpage" ref={shellRef}>
      <div className="twork">
        <aside className="subnav">
          <div className="sn-title">일정</div>
          <button className="sn-new">
            <Icon name="plus" /> 새 일정
          </button>
          <MiniCal
            sel={selDay}
            today={bundle.today}
            weekdays={bundle.weekdays}
            eventsByDay={countByDay(events)}
            onSel={(n) => {
              setSelDay(n);
              if (view !== "day") setView("day");
            }}
          />
          <div className="sn-label">내 캘린더</div>
          <CalToggleList
            calendars={bundle.calendars}
            calOn={calOn}
            onToggle={(id) => setCalOn((s) => ({ ...s, [id]: s[id] === false }))}
          />
          <div className="sn-foot">
            <div className="av">지</div>
            <div className="txt">
              <b>지우님</b>
              <span>Pro 플랜</span>
            </div>
          </div>
        </aside>

        <main className="cmain">
          <div className="chead">
            <button className="ch-arrow" aria-label="이전">
              <Icon name="chev" className="ic flip" />
            </button>
            <button className="ch-arrow" aria-label="다음">
              <Icon name="chev" />
            </button>
            <h1 className="ch-title">{title}</h1>
            <button className="ch-today" onClick={() => setSelDay(bundle.today)}>
              오늘
            </button>
            <span className="ch-spacer" />
            <button
              className={"ch-focus" + (focusOn ? " on" : "")}
              onClick={() => setFocusOn((v) => !v)}
              aria-pressed={focusOn}
            >
              <Icon name="spark" />
              집중 블록
            </button>
            <div className="view-seg" role="tablist">
              {VIEWS.map((v) => (
                <button
                  key={v.id}
                  role="tab"
                  aria-selected={view === v.id}
                  className={view === v.id ? "on" : ""}
                  onClick={() => setView(v.id)}
                >
                  {v.label}
                </button>
              ))}
            </div>
          </div>

          <div className="ai-strip">
            <div className="ai-ic">
              <Icon name="spark" />
            </div>
            <p>
              오늘 일정 중 <b>14:00 분기 전략 미팅</b>이 가장 중요해요. 미팅 사이 빈 시간엔 가벼운
              일을, <b>오후 15:10 빈 블록</b>엔 ‘분기 리포트’ 딥 워크를 자동으로 배치해뒀어요. 16:00
              ‘치과 예약’은 1:1과 가까워 15분 앞당기길 추천드려요.
            </p>
          </div>

          {view === "week" && (
            <WeekView
              events={events}
              focusBlocks={focusBlocks}
              calMap={calMap}
              week={bundle.week}
              weekdays={bundle.weekdays}
              today={bundle.today}
              onOpen={openEv}
            />
          )}
          {view === "month" && (
            <MonthView
              events={events}
              calMap={calMap}
              weekdays={bundle.weekdays}
              today={bundle.today}
              onOpen={openEv}
              onSelDay={(n) => {
                setSelDay(n);
                setView("day");
              }}
            />
          )}
          {view === "day" && (
            <DayView
              events={events}
              focusBlocks={focusBlocks}
              calMap={calMap}
              day={selDay}
              week={bundle.week}
              weekdays={bundle.weekdays}
              today={bundle.today}
              onOpen={openEv}
              onMeet={openMeet}
            />
          )}
        </main>
      </div>

      {pop && (
        <EvPopover
          ev={pop.ev}
          x={pop.x}
          y={pop.y}
          cal={calMap[pop.ev.cal]}
          onClose={() => setPop(null)}
          onMeet={openMeet}
        />
      )}
      {meetEv && (
        <MeetDrawer ev={meetEv} cal={calMap[meetEv.cal]} onClose={() => setMeetEv(null)} />
      )}
    </div>
  );
}
