"use client";

// Radial fan chart of a focus person's ancestors (family-chart has no fan).
// Each generation is a ring; slot p in generation g descends from slot floor(p/2)
// in g-1. Click a wedge to refocus.

type Props = {
  focusId: string;
  parentsOf: (id: string) => string[];
  nameOf: (id: string) => string;
  yearOf: (id: string) => string;
  onSelect: (id: string) => void;
  generations?: number;
};

const SIZE = 720;
const CENTER = SIZE / 2;
const FOCUS_R = 46;
const SPAN = Math.PI * 1.6; // 288° fan

function polar(r: number, a: number): [number, number] {
  // a = 0 points up, increasing clockwise.
  return [CENTER + r * Math.sin(a), CENTER - r * Math.cos(a)];
}

function sector(r0: number, r1: number, a0: number, a1: number): string {
  const [x0, y0] = polar(r1, a0);
  const [x1, y1] = polar(r1, a1);
  const [x2, y2] = polar(r0, a1);
  const [x3, y3] = polar(r0, a0);
  const large = a1 - a0 > Math.PI ? 1 : 0;
  return `M${x0} ${y0} A${r1} ${r1} 0 ${large} 1 ${x1} ${y1} L${x2} ${y2} A${r0} ${r0} 0 ${large} 0 ${x3} ${y3} Z`;
}

function clip(s: string, n: number): string {
  return s.length > n ? s.slice(0, n - 1) + "…" : s;
}

export function FanChart({
  focusId,
  parentsOf,
  nameOf,
  yearOf,
  onSelect,
  generations = 4,
}: Props) {
  const gens: (string | null)[][] = [[focusId]];
  for (let g = 1; g <= generations; g++) {
    const row: (string | null)[] = [];
    for (const slot of gens[g - 1]) {
      const ps = slot ? parentsOf(slot) : [];
      row.push(ps[0] ?? null, ps[1] ?? null);
    }
    gens.push(row);
  }

  const ringT = (CENTER - 60 - FOCUS_R) / generations;
  const start = -SPAN / 2;
  const wedges: React.ReactNode[] = [];

  for (let g = 1; g <= generations; g++) {
    const row = gens[g];
    const w = SPAN / row.length;
    const r0 = FOCUS_R + (g - 1) * ringT;
    const r1 = FOCUS_R + g * ringT;
    row.forEach((id, i) => {
      const a0 = start + i * w;
      const a1 = start + (i + 1) * w;
      const mid = (a0 + a1) / 2;
      const [tx, ty] = polar((r0 + r1) / 2, mid);
      let deg = (mid * 180) / Math.PI;
      if (deg > 90 || deg < -90) deg += 180; // keep text upright
      wedges.push(
        <g
          key={`${g}-${i}`}
          onClick={() => id && onSelect(id)}
          style={{ cursor: id ? "pointer" : "default" }}
        >
          <path
            d={sector(r0 + 1, r1 - 1, a0 + 0.004, a1 - 0.004)}
            fill={id ? "var(--surface)" : "transparent"}
            stroke="var(--line)"
          />
          {id && (
            <text
              x={tx}
              y={ty}
              transform={`rotate(${deg} ${tx} ${ty})`}
              textAnchor="middle"
              dominantBaseline="middle"
              style={{ fontSize: g >= 3 ? 9 : 11, fill: "var(--foreground)" }}
            >
              {clip(nameOf(id), g >= 3 ? 12 : 18)}
            </text>
          )}
        </g>,
      );
    });
  }

  const [fx, fy] = [CENTER, CENTER];
  return (
    <div className="overflow-auto">
      <svg viewBox={`0 0 ${SIZE} ${SIZE}`} className="mx-auto block w-full max-w-3xl">
        {wedges}
        <circle cx={fx} cy={fy} r={FOCUS_R} fill="var(--color-bronze)" />
        <text
          x={fx}
          y={fy - 4}
          textAnchor="middle"
          dominantBaseline="middle"
          style={{ fontSize: 12, fill: "var(--color-paper)", fontWeight: 600 }}
        >
          {clip(nameOf(focusId), 12)}
        </text>
        <text
          x={fx}
          y={fy + 12}
          textAnchor="middle"
          dominantBaseline="middle"
          style={{ fontSize: 10, fill: "var(--color-paper)" }}
        >
          {yearOf(focusId)}
        </text>
      </svg>
    </div>
  );
}
