/* global React */
const { useState: useStateL, useEffect: useEffectL, useRef: useRefL } = React;

/* ──────────────────────────────────────────
   LEAK MAP — animated funnel diagram
   Dots flow down through the funnel; some "leak" out the sides.
   Each leak is a labeled, clickable revenue loss.
   ────────────────────────────────────────── */

const LEAKS = [
  {
    n: "01",
    title: "The missed call",
    lost: "~$340",
    period: "/missed call avg",
    desc:
      "A prospect calls during a job. Nobody picks up. They hang up and dial the next business on Google. The average local service business loses 1 in 4 leads here.",
  },
  {
    n: "02",
    title: "The form that sat",
    lost: "−78%",
    period: "conversion past 5 min",
    desc:
      "Responding to a web form in 5 minutes vs. 30 minutes drops your conversion rate by ~78%. Most service businesses respond in hours, not minutes.",
  },
  {
    n: "03",
    title: "The follow-up that never came",
    lost: "44%",
    period: "stop after 1 try",
    desc:
      "Most quotes get one follow-up attempt. The buyer needed 3–5 touches. The deal didn't go cold — the salesperson did.",
  },
  {
    n: "04",
    title: "The review never asked for",
    lost: "~12 / yr",
    period: "reviews never captured",
    desc:
      "Happy customers don't volunteer reviews — they need to be asked at the right moment. Every uncaptured review is a lower ranking for every search after.",
  },
  {
    n: "05",
    title: "The reactivation never sent",
    lost: "8–12%",
    period: "of past clients",
    desc:
      "A list of past customers is the cheapest source of revenue in your business. Most owners never email it. The leads were already paid for.",
  },
];

function LeakCanvas({ activeIdx, onHover }) {
  // SVG funnel with flowing dots. Some dots get "leaked" out at each stage.
  const ref = useRefL(null);
  const [tick, setTick] = useStateL(0);
  const reduceMotion = useRefL(
    typeof window !== "undefined" &&
      window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches
  );

  useEffectL(() => {
    if (reduceMotion.current) return;
    let raf;
    let last = performance.now();
    const loop = (t) => {
      if (t - last > 60) {
        setTick((v) => v + 1);
        last = t;
      }
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);

  // Geometry
  const W = 500;
  const H = 400;
  const topY = 40;
  const stages = [
    { y: 80, label: "100 visitors", w: 380 },
    { y: 145, label: "Calls + forms", w: 300 },
    { y: 210, label: "Responded to", w: 220 },
    { y: 275, label: "Followed up", w: 150 },
    { y: 340, label: "Booked", w: 90 },
  ];

  // Generate "leak" positions for each stage
  const leakSides = [-1, 1, -1, 1, -1]; // alternating sides

  // Flowing dots
  const dots = [];
  for (let i = 0; i < 16; i++) {
    const phase = (i * 0.0625 + tick * 0.012) % 1;
    const y = topY + phase * (stages[stages.length - 1].y - topY + 30);
    // Funnel narrowing
    let widthAtY = 380;
    for (let s = 0; s < stages.length - 1; s++) {
      if (y >= stages[s].y && y <= stages[s + 1].y) {
        const t = (y - stages[s].y) / (stages[s + 1].y - stages[s].y);
        widthAtY = stages[s].w + (stages[s + 1].w - stages[s].w) * t;
        break;
      }
    }
    if (y > stages[stages.length - 1].y) widthAtY = stages[stages.length - 1].w;
    const x =
      W / 2 +
      Math.sin(phase * Math.PI * 2 + i) * (widthAtY * 0.3) +
      ((i * 31) % widthAtY) -
      widthAtY / 2;
    const opacity = Math.min(1, (1 - phase) * 1.4);
    dots.push({ x, y, opacity, key: i });
  }

  // Leak dots (the lost ones) — animated at each stage
  const leakDots = [];
  stages.slice(0, -1).forEach((stage, idx) => {
    const side = leakSides[idx];
    const count = 4 - Math.floor(idx / 2);
    for (let i = 0; i < count; i++) {
      const phase = ((i / count) + tick * 0.008 + idx * 0.2) % 1;
      const startX = W / 2 + (side * stage.w) / 2;
      const x = startX + side * phase * 80;
      const y = stage.y + phase * 30 + Math.sin(phase * 4) * 4;
      const opacity = Math.max(0, 1 - phase * 1.6);
      leakDots.push({
        x,
        y,
        opacity,
        key: `l${idx}-${i}`,
        highlight: activeIdx === idx,
      });
    }
  });

  return (
    <svg ref={ref} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet">
      <defs>
        <linearGradient id="funnelStroke" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#14130f" stopOpacity="0.7" />
          <stop offset="100%" stopColor="#14130f" stopOpacity="0.3" />
        </linearGradient>
      </defs>

      {/* Funnel outline */}
      <path
        d={`
          M ${W / 2 - stages[0].w / 2} ${stages[0].y}
          L ${W / 2 - stages[stages.length - 1].w / 2} ${
          stages[stages.length - 1].y
        }
          L ${W / 2 + stages[stages.length - 1].w / 2} ${
          stages[stages.length - 1].y
        }
          L ${W / 2 + stages[0].w / 2} ${stages[0].y}
          Z
        `}
        fill="none"
        stroke="url(#funnelStroke)"
        strokeWidth="1"
      />

      {/* Stage lines + labels */}
      {stages.map((s, i) => (
        <g key={i}>
          <line
            x1={W / 2 - s.w / 2}
            y1={s.y}
            x2={W / 2 + s.w / 2}
            y2={s.y}
            stroke="#14130f"
            strokeOpacity="0.18"
            strokeWidth="1"
            strokeDasharray="2 3"
          />
          <text
            x={W / 2}
            y={s.y - 6}
            textAnchor="middle"
            fontFamily="JetBrains Mono, monospace"
            fontSize="9"
            letterSpacing="0.8"
            fill="#807a6b"
          >
            {s.label.toUpperCase()}
          </text>
        </g>
      ))}

      {/* Flowing dots (the leads that made it through) */}
      {dots.map((d) => (
        <circle
          key={d.key}
          cx={d.x}
          cy={d.y}
          r="3"
          fill="#14130f"
          opacity={d.opacity * 0.7}
        />
      ))}

      {/* Leak indicators — labeled arrows at each stage */}
      {stages.slice(0, -1).map((stage, idx) => {
        const side = leakSides[idx];
        const labelX = W / 2 + side * (stage.w / 2 + 60);
        const labelY = stage.y + 8;
        const isActive = activeIdx === idx;
        return (
          <g
            key={`lk-${idx}`}
            style={{ cursor: "pointer" }}
            onMouseEnter={() => onHover(idx)}
            onMouseLeave={() => onHover(null)}
            onClick={() => onHover(idx)}
          >
            <line
              x1={W / 2 + (side * stage.w) / 2}
              y1={stage.y}
              x2={labelX - side * 6}
              y2={labelY}
              stroke={isActive ? "#d9532a" : "#c43d1d"}
              strokeOpacity={isActive ? 1 : 0.5}
              strokeWidth={isActive ? "1.5" : "1"}
            />
            <circle
              cx={labelX - side * 6}
              cy={labelY}
              r={isActive ? "4" : "3"}
              fill="#c43d1d"
              opacity={isActive ? 1 : 0.7}
            />
            <text
              x={labelX}
              y={labelY + 3}
              textAnchor={side === 1 ? "start" : "end"}
              fontFamily="JetBrains Mono, monospace"
              fontSize="9"
              letterSpacing="0.8"
              fill={isActive ? "#d9532a" : "#807a6b"}
              fontWeight={isActive ? 600 : 400}
            >
              LEAK 0{idx + 1}
            </text>
          </g>
        );
      })}

      {/* Animated leak dots */}
      {leakDots.map((d) => (
        <circle
          key={d.key}
          cx={d.x}
          cy={d.y}
          r={d.highlight ? "3" : "2"}
          fill="#c43d1d"
          opacity={d.opacity * (d.highlight ? 1 : 0.6)}
        />
      ))}
    </svg>
  );
}

function LeakMap() {
  const [active, setActive] = useStateL(0);
  return (
    <div className="leakmap">
      <div className="leak-canvas">
        <LeakCanvas activeIdx={active} onHover={(i) => setActive(i ?? active)} />
      </div>

      <div className="leak-list">
        {LEAKS.map((l, i) => (
          <div
            key={i}
            className={`leak-row ${active === i ? "active" : ""}`}
            onMouseEnter={() => setActive(i)}
            onClick={() => setActive(i)}
          >
            <div className="num">{l.n}</div>
            <div>
              <div className="title">{l.title}</div>
              <div className="desc">{l.desc}</div>
            </div>
            <div className="lost">
              <span className="v">{l.lost}</span>
              {l.period}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

window.LeakMap = LeakMap;
