// frontend/components/journey/JourneyBoard.tsx
// 4컬럼 보드 + 실시간 베지어 커넥터 (원본 Board).
// DOM 위치를 측정해 SVG cubic Bézier 곡선을 그린다.
"use client";
import { useRef, useState, useCallback, useLayoutEffect, useMemo } from "react";
import { JourneyColumn } from "./JourneyColumn";
import { RoutineFlowCard, TaskFlowCard, MeetFlowCard } from "./FlowCard";
import { FinishTile } from "./FinishTile";
import type { JourneyStage, JourneyCards, JourneyLink, JourneyPerson } from "@/lib/types";

type Props = {
  stages: JourneyStage[];
  cards: JourneyCards;
  links: JourneyLink[];
  people: JourneyPerson[];
};

type ComputedPath = {
  key: string;
  from: string;
  to: string;
  color: string;
  dash: boolean;
  d: string;
  x1: number;
  y1: number;
  x2: number;
  y2: number;
};

export function JourneyBoard({ stages, cards, links, people }: Props) {
  const boardRef = useRef<HTMLDivElement>(null);
  const nodes = useRef<Record<string, HTMLElement | null>>({});
  const [paths, setPaths] = useState<ComputedPath[]>([]);
  const [size, setSize] = useState({ w: 0, h: 0 });
  const [hover, setHover] = useState<string | null>(null);

  // 오전 집중(s2) 작업의 done 토글은 로컬 state (원본 toggle)
  const [done, setDone] = useState<Record<string, boolean>>(() =>
    Object.fromEntries(cards.s2.map((c) => [c.node, !!c.done])),
  );
  const peopleById = useMemo(
    () => Object.fromEntries(people.map((p) => [p.id, p])),
    [people],
  );

  const setNode = (id: string) => (el: HTMLElement | null) => {
    nodes.current[id] = el;
  };

  const compute = useCallback(() => {
    const board = boardRef.current;
    if (!board) return;
    const br = board.getBoundingClientRect();
    const out: ComputedPath[] = [];
    for (const lk of links) {
      const a = nodes.current[lk.from_node];
      const b = nodes.current[lk.to_node];
      if (!a || !b) continue;
      const ar = a.getBoundingClientRect();
      const bb = b.getBoundingClientRect();
      const x1 = ar.right - br.left;
      const y1 = ar.top - br.top + ar.height / 2;
      const x2 = bb.left - br.left;
      const y2 = bb.top - br.top + bb.height / 2;
      const dx = Math.max(36, (x2 - x1) * 0.5);
      out.push({
        key: lk.from_node + ">" + lk.to_node,
        from: lk.from_node,
        to: lk.to_node,
        color: lk.tone === "ink" ? "var(--ink)" : `var(--${lk.tone})`,
        dash: lk.dash,
        d: `M${x1},${y1} C${x1 + dx},${y1} ${x2 - dx},${y2} ${x2},${y2}`,
        x1,
        y1,
        x2,
        y2,
      });
    }
    setPaths(out);
    setSize({ w: br.width, h: br.height });
  }, [links]);

  useLayoutEffect(() => {
    compute();
    const raf = requestAnimationFrame(compute);
    const onR = () => compute();
    window.addEventListener("resize", onR);
    const ro = new ResizeObserver(compute);
    if (boardRef.current) ro.observe(boardRef.current);
    if (document.fonts?.ready) document.fonts.ready.then(compute);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", onR);
      ro.disconnect();
    };
  }, [compute, done]);

  // 이웃 맵(양방향) — 호버 강조용 (원본 neighbors)
  const neighbors = useMemo(() => {
    const m: Record<string, Set<string>> = {};
    for (const l of links) {
      (m[l.from_node] = m[l.from_node] || new Set()).add(l.to_node);
      (m[l.to_node] = m[l.to_node] || new Set()).add(l.from_node);
    }
    return m;
  }, [links]);

  const isLit = (node: string) =>
    !!hover && (node === hover || (neighbors[hover]?.has(node) ?? false));
  const cls = (node: string, base: string) =>
    base + (isLit(node) ? " lit" : "") + (hover && !isLit(node) ? " mute" : "");
  const pathState = (p: ComputedPath) =>
    !hover ? "" : p.from === hover || p.to === hover ? " on" : " off";
  const hoverProps = (node: string, base: string) => ({
    className: cls(node, base),
    onMouseEnter: () => setHover(node),
    onMouseLeave: () => setHover(null),
  });
  const toggle = (node: string) => setDone((d) => ({ ...d, [node]: !d[node] }));

  return (
    <div className="jx-board" ref={boardRef}>
      <svg
        className="jx-svg"
        width={size.w}
        height={size.h}
        viewBox={`0 0 ${size.w} ${size.h}`}
        aria-hidden
      >
        {paths.map((p) => (
          <g key={p.key} className={"jx-link" + pathState(p)}>
            <path
              className="jx-line"
              d={p.d}
              stroke={p.color}
              fill="none"
              strokeDasharray={p.dash ? "1 7" : "none"}
            />
            <circle cx={p.x1} cy={p.y1} r="3.4" fill={p.color} className="jx-dot" />
            <circle cx={p.x2} cy={p.y2} r="3.4" fill={p.color} className="jx-dot" />
          </g>
        ))}
      </svg>

      {/* 1 — 아침 준비 (routine) */}
      <JourneyColumn stage={stages[0]}>
        {cards.s1.map((c) => (
          <RoutineFlowCard
            key={c.node}
            card={c}
            ref={setNode(c.node)}
            hover={hoverProps(c.node, "fcard")}
          />
        ))}
      </JourneyColumn>

      {/* 2 — 오전 집중 (task, 체크 토글) */}
      <JourneyColumn
        stage={stages[1]}
        count={`${cards.s2.filter((t) => !done[t.node]).length}/4`}
      >
        {cards.s2.map((t) => (
          <TaskFlowCard
            key={t.node}
            card={t}
            person={peopleById[t.who]}
            done={!!done[t.node]}
            onToggle={() => toggle(t.node)}
            ref={setNode(t.node)}
            hover={hoverProps(t.node, "fcard task" + (done[t.node] ? " done" : ""))}
          />
        ))}
      </JourneyColumn>

      {/* 3 — 오후 협업 (meet) */}
      <JourneyColumn stage={stages[2]}>
        {cards.s3.map((e) => (
          <MeetFlowCard
            key={e.node}
            card={e}
            person={peopleById[e.who]}
            ref={setNode(e.node)}
            hover={hoverProps(e.node, "fcard")}
          />
        ))}
      </JourneyColumn>

      {/* 4 — 마무리 & 내일 (tile) */}
      <JourneyColumn stage={stages[3]}>
        <div className="tiles">
          {cards.s4.map((t) => (
            <FinishTile
              key={t.node}
              card={t}
              ref={setNode(t.node)}
              hover={hoverProps(t.node, "tile" + (t.hi ? " hi" : ""))}
            />
          ))}
        </div>
      </JourneyColumn>
    </div>
  );
}
