// Animated forgetting curve, blue palette
const ForgettingCurve = () => {
  const [t, setT] = React.useState(0);
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const obs = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) setInView(true);
    }, { threshold: 0.3 });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  React.useEffect(() => {
    if (!inView) return;
    let raf, start;
    const tick = (ts) => {
      if (!start) start = ts;
      const elapsed = (ts - start) / 1000;
      const progress = Math.min(elapsed / 2.4, 1);
      setT(1 - Math.pow(1 - progress, 3));
      if (progress < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView]);

  const W = 600, H = 360;
  const padL = 56, padR = 24, padT = 24, padB = 48;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const days = 30;

  const curveNoReview = [];
  for (let i = 0; i <= 100; i++) {
    const x = (i / 100) * days;
    const y = 0.18 + 0.82 * Math.exp(-x / 3.5);
    curveNoReview.push([x, y]);
  }

  const reviews = [1, 3, 7, 16, 30];
  const curveWithReview = [];
  for (let i = 0; i <= 200; i++) {
    const x = (i / 200) * days;
    let activeReview = 0, activeDecay = 3.5;
    for (let r = 0; r < reviews.length; r++) {
      if (x >= reviews[r]) { activeReview = reviews[r]; activeDecay = 3.5 + r * 4; }
    }
    const dx = x - activeReview;
    const y = 0.2 + 0.8 * Math.exp(-dx / activeDecay);
    curveWithReview.push([x, y]);
  }

  const xScale = (x) => padL + (x / days) * innerW;
  const yScale = (y) => padT + (1 - y) * innerH;
  const visibleX = t * days;

  const buildPath = (curve) => {
    const visible = curve.filter(([x]) => x <= visibleX);
    if (!visible.length) return "";
    return visible.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${xScale(x).toFixed(1)} ${yScale(y).toFixed(1)}`).join(" ");
  };

  const fillPath = (curve) => {
    const visible = curve.filter(([x]) => x <= visibleX);
    if (!visible.length) return "";
    const path = visible.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${xScale(x).toFixed(1)} ${yScale(y).toFixed(1)}`).join(" ");
    const lastX = visible[visible.length - 1][0];
    return `${path} L ${xScale(lastX).toFixed(1)} ${yScale(0.18).toFixed(1)} L ${xScale(0).toFixed(1)} ${yScale(0.18).toFixed(1)} Z`;
  };

  const dayLabels = [0, 7, 14, 21, 30];
  const yLabels = [{ y: 1, label: "100%" }, { y: 0.5, label: "50%" }, { y: 0.2, label: "20%" }];

  return (
    <div ref={ref} style={{ width: "100%", background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 24, padding: 24 }}>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: "100%", height: "auto", display: "block" }}>
        <defs>
          <linearGradient id="noReviewFill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="var(--muted)" stopOpacity="0.18" />
            <stop offset="1" stopColor="var(--muted)" stopOpacity="0" />
          </linearGradient>
          <linearGradient id="withReviewFill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="var(--blue)" stopOpacity="0.28" />
            <stop offset="1" stopColor="var(--blue)" stopOpacity="0" />
          </linearGradient>
        </defs>

        {yLabels.map(({ y, label }) => (
          <g key={label}>
            <line x1={padL} y1={yScale(y)} x2={W - padR} y2={yScale(y)} stroke="var(--line)" strokeWidth="1" strokeDasharray="2 4" />
            <text x={padL - 12} y={yScale(y) + 4} textAnchor="end" fontSize="11" fill="var(--muted)" fontFamily="-apple-system, sans-serif" fontWeight="500">{label}</text>
          </g>
        ))}

        <line x1={padL} y1={H - padB} x2={W - padR} y2={H - padB} stroke="var(--line)" strokeWidth="1" />
        {dayLabels.map((d) => (
          <g key={d}>
            <line x1={xScale(d)} y1={H - padB} x2={xScale(d)} y2={H - padB + 6} stroke="var(--muted)" strokeWidth="1" />
            <text x={xScale(d)} y={H - padB + 22} textAnchor="middle" fontSize="11" fill="var(--muted)" fontFamily="-apple-system, sans-serif" fontWeight="500">Day {d}</text>
          </g>
        ))}

        <text x={20} y={padT + 10} fontSize="10" fill="var(--muted)" fontFamily="-apple-system, sans-serif" fontWeight="600" letterSpacing="1">RETENTION</text>

        <path d={fillPath(curveNoReview)} fill="url(#noReviewFill)" />
        <path d={buildPath(curveNoReview)} fill="none" stroke="var(--muted)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" strokeDasharray="4 4" opacity="0.7" />

        <path d={fillPath(curveWithReview)} fill="url(#withReviewFill)" />
        <path d={buildPath(curveWithReview)} fill="none" stroke="var(--blue)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />

        {reviews.map((r) => visibleX >= r && (
          <g key={r}>
            <line x1={xScale(r)} y1={yScale(1)} x2={xScale(r)} y2={H - padB} stroke="var(--blue)" strokeWidth="1" strokeDasharray="2 3" opacity="0.4" />
            <circle cx={xScale(r)} cy={yScale(1)} r="5" fill="var(--blue)" stroke="var(--surface)" strokeWidth="2" />
          </g>
        ))}

        <g transform={`translate(${W - padR - 200}, ${padT + 10})`}>
          <g>
            <line x1="0" y1="0" x2="20" y2="0" stroke="var(--muted)" strokeWidth="2" strokeDasharray="4 4" />
            <text x="28" y="4" fontSize="11.5" fill="var(--text-soft)" fontFamily="-apple-system, sans-serif">Without review</text>
          </g>
          <g transform="translate(0, 20)">
            <line x1="0" y1="0" x2="20" y2="0" stroke="var(--blue)" strokeWidth="2.5" />
            <circle cx="10" cy="0" r="3.5" fill="var(--blue)" />
            <text x="28" y="4" fontSize="11.5" fill="var(--text-soft)" fontFamily="-apple-system, sans-serif">With spaced repetition</text>
          </g>
        </g>
      </svg>
    </div>
  );
};

window.ForgettingCurve = ForgettingCurve;
