// river-map.jsx — Interactive Middle Fork map + day scrubber.
// Stylized topo map with a winding river, six camp markers, and a tiny raft
// that travels day by day. Side panel narrates the current day.

const RIVER_DAYS = [
  {
    day: 1,
    date: "Sun, Jun 21",
    title: "Boundary → Joe Bump",
    camp: "Joe Bump Camp",
    miles: 14,
    elev: "5,940 → 5,560",
    runtime: "5 hrs",
    narrative: "Launch morning. Boundary Creek, fast cold water, and the first taste of canyon walls. Velvet Falls comes up sooner than you'd expect — pay attention on the right.",
    marks: ["Velvet Falls", "First camp"],
    pos: { x: 0.18, y: 0.08 },
  },
  {
    day: 2,
    date: "Mon, Jun 22",
    title: "Joe Bump → Marble",
    camp: "Marble Creek Camp",
    miles: 17,
    elev: "5,560 → 5,250",
    runtime: "6 hrs",
    narrative: "Pistol Creek Rapid headlines the day. Granite walls open into stretches of ponderosa. Marble Creek is a postcard.",
    marks: ["Pistol Creek", "Hike option"],
    pos: { x: 0.32, y: 0.24 },
  },
  {
    day: 3,
    date: "Tue, Jun 23",
    title: "Marble → Loon",
    camp: "Loon Creek Camp",
    miles: 12,
    elev: "5,250 → 4,920",
    runtime: "5 hrs",
    narrative: "Short river day, long afternoon. Tappan Falls in the morning, then time to soak — Sunflower or Loon hot springs depending on water level and group mood.",
    marks: ["Tappan Falls", "Hot Springs"],
    pos: { x: 0.45, y: 0.42 },
  },
  {
    day: 4,
    date: "Wed, Jun 24",
    title: "Loon → Camas",
    camp: "Camas Creek Camp",
    miles: 16,
    elev: "4,920 → 4,560",
    runtime: "6 hrs",
    narrative: "Deeper into the wilderness. Bighorn sheep on the canyon walls if you're paying attention. Fishing pockets open up if your guides give the nod.",
    marks: ["Bighorn sheep", "Fishing"],
    pos: { x: 0.58, y: 0.58 },
  },
  {
    day: 5,
    date: "Thu, Jun 25",
    title: "Camas → Big Creek",
    camp: "Big Creek Camp",
    miles: 18,
    elev: "4,560 → 4,140",
    runtime: "7 hrs",
    narrative: "The big-water day. Redside Rapid, Weber Rapid, and a string of Class IV that earns its name. Big Creek camp is a reward — wide, sandy, generous.",
    marks: ["Redside", "Weber"],
    pos: { x: 0.7, y: 0.72 },
  },
  {
    day: 6,
    date: "Fri, Jun 26",
    title: "Big Creek → Cache Bar",
    camp: "Takeout · Cache Bar",
    miles: 23,
    elev: "4,140 → 3,640",
    runtime: "7 hrs",
    narrative: "Impassable Canyon finale. Vertical granite, the river compressed, and the longest day on the water. By dinner you're in Salmon. Boots dry by morning.",
    marks: ["Impassable Canyon", "Takeout"],
    pos: { x: 0.84, y: 0.92 },
  },
];

// River path is a hand-tuned curve through all six camp positions —
// generated once so the boat tween follows the same line the eye does.
const RIVER_PATH = "M 60 30 C 80 80, 100 100, 130 130 S 170 200, 200 250 S 240 320, 270 360 S 320 430, 360 470";

function RiverMap() {
  const [active, setActive] = React.useState(0);
  const [playing, setPlaying] = React.useState(false);
  const pathRef = React.useRef(null);
  const [pathLen, setPathLen] = React.useState(800);

  React.useEffect(() => {
    if (pathRef.current) {
      setPathLen(pathRef.current.getTotalLength());
    }
  }, []);

  React.useEffect(() => {
    if (!playing) return;
    const id = setInterval(() => {
      setActive((a) => {
        if (a >= RIVER_DAYS.length - 1) {
          setPlaying(false);
          return a;
        }
        return a + 1;
      });
    }, 1800);
    return () => clearInterval(id);
  }, [playing]);

  const day = RIVER_DAYS[active];
  // The active marker's geometric point along the river path — used to
  // place the boat. We compute it from the SVG path length so the dot
  // tracks the curve exactly, not just the lat/long pos guess.
  const boatPos = React.useMemo(() => {
    if (!pathRef.current) return { x: 60, y: 30 };
    const fraction = (active + 0.5) / RIVER_DAYS.length;
    const p = pathRef.current.getPointAtLength(pathLen * fraction);
    return { x: p.x, y: p.y };
  }, [active, pathLen]);

  // Day markers placed along the river path at evenly distributed lengths,
  // not by hand-coded lat/long — keeps them riding the curve cleanly.
  const stopPositions = React.useMemo(() => {
    if (!pathRef.current) return RIVER_DAYS.map(() => ({ x: 0, y: 0 }));
    return RIVER_DAYS.map((_, i) => {
      const fraction = (i + 0.5) / RIVER_DAYS.length;
      const p = pathRef.current.getPointAtLength(pathLen * fraction);
      return { x: p.x, y: p.y };
    });
  }, [pathLen]);

  const totalMiles = RIVER_DAYS.reduce((sum, d) => sum + d.miles, 0);

  return (
    <div className="river-frame">
      <div className="river-grid">
        {/* ── MAP ─────────────────────────────────────────────────── */}
        <div className="river-map-wrap">
          <svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid meet">
            <defs>
              <pattern id="topo-lines" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                <path d="M0 10 Q5 6 10 10 T20 10" stroke="currentColor" strokeWidth="0.5" fill="none" opacity="0.18"/>
              </pattern>
            </defs>

            {/* Topographic background — concentric blobs */}
            <g style={{ color: "var(--ink)" }} opacity="0.5">
              <ellipse cx="100" cy="80" rx="160" ry="110" fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="100" cy="80" rx="120" ry="80"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="100" cy="80" rx="80"  ry="50"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="100" cy="80" rx="40"  ry="22"  fill="none" stroke="currentColor" strokeWidth="0.4" />

              <ellipse cx="340" cy="160" rx="120" ry="90"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="340" cy="160" rx="80"  ry="60"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="340" cy="160" rx="40"  ry="30"  fill="none" stroke="currentColor" strokeWidth="0.4" />

              <ellipse cx="60"  cy="320" rx="120" ry="80"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="60"  cy="320" rx="80"  ry="50"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="60"  cy="320" rx="40"  ry="25"  fill="none" stroke="currentColor" strokeWidth="0.4" />

              <ellipse cx="320" cy="400" rx="100" ry="70"  fill="none" stroke="currentColor" strokeWidth="0.4" />
              <ellipse cx="320" cy="400" rx="60"  ry="40"  fill="none" stroke="currentColor" strokeWidth="0.4" />
            </g>

            {/* Compass rose */}
            <g transform="translate(355, 50)" style={{ color: "var(--ink)" }}>
              <circle cx="0" cy="0" r="22" fill="var(--paper)" stroke="currentColor" strokeWidth="1" />
              <path d="M0 -18 L4 0 L0 18 L-4 0 Z" fill="currentColor" />
              <path d="M-18 0 L0 -4 L18 0 L0 4 Z" fill="currentColor" opacity="0.4" />
              <text x="0" y="-26" textAnchor="middle" fontSize="6" fontFamily="JetBrains Mono" fontWeight="700" fill="currentColor">N</text>
            </g>

            {/* River shadow */}
            <path
              d={RIVER_PATH}
              stroke="var(--ink)"
              strokeWidth="8"
              fill="none"
              strokeLinecap="round"
              opacity="0.1"
              transform="translate(2,2)"
            />
            {/* The river itself */}
            <path
              ref={pathRef}
              d={RIVER_PATH}
              stroke="var(--sky)"
              strokeWidth="4.5"
              fill="none"
              strokeLinecap="round"
            />
            {/* River dashes (highlight) */}
            <path
              d={RIVER_PATH}
              stroke="var(--paper)"
              strokeWidth="1"
              fill="none"
              strokeLinecap="round"
              strokeDasharray="4 8"
              opacity="0.7"
            />

            {/* Start & end labels */}
            <g style={{ color: "var(--ink)" }} fontFamily="JetBrains Mono" fontWeight="700" fontSize="6.5" letterSpacing="0.5">
              <text x="62" y="22" fill="currentColor" textAnchor="start">BOUNDARY CREEK</text>
              <text x="62" y="29" fill="var(--muted)" textAnchor="start" fontSize="5">PUT-IN · 5,940 FT</text>

              <text x="358" y="478" fill="currentColor" textAnchor="end">CACHE BAR</text>
              <text x="358" y="486" fill="var(--muted)" textAnchor="end" fontSize="5">TAKEOUT · 3,640 FT</text>
            </g>

            {/* Mountain glyphs scattered */}
            <g style={{ color: "var(--ink-soft)" }} opacity="0.55">
              <path d="M 230 70 l 8 -14 l 8 14 z" fill="currentColor" />
              <path d="M 245 75 l 6 -10 l 6 10 z" fill="currentColor" />
              <path d="M 30 230 l 8 -14 l 8 14 z" fill="currentColor" />
              <path d="M 280 250 l 8 -14 l 8 14 z" fill="currentColor" />
              <path d="M 295 255 l 6 -10 l 6 10 z" fill="currentColor" />
              <path d="M 70 410 l 8 -14 l 8 14 z" fill="currentColor" />
              <path d="M 360 290 l 8 -14 l 8 14 z" fill="currentColor" />
            </g>

            {/* Pine-tree marks */}
            <g style={{ color: "var(--pine)" }} opacity="0.65">
              {[[150, 100], [220, 180], [50, 180], [310, 320], [120, 350], [200, 420]].map(([x, y], i) => (
                <g key={i} transform={`translate(${x},${y})`}>
                  <path d="M0 0 l -3 5 l 6 0 z M0 3 l -3.5 6 l 7 0 z M0 6 l -4 7 l 8 0 z" fill="currentColor" />
                </g>
              ))}
            </g>

            {/* Camp markers — placed along the path */}
            {stopPositions.map((p, i) => {
              const isActive = i === active;
              return (
                <g key={i} transform={`translate(${p.x}, ${p.y})`}
                   onClick={() => setActive(i)}
                   style={{ cursor: "pointer" }}>
                  <circle r="11" fill="var(--paper)" stroke="var(--ink)" strokeWidth="1.2" />
                  {isActive ? (
                    <circle r="7" fill="var(--accent)" />
                  ) : i < active ? (
                    <circle r="5" fill="var(--accent)" opacity="0.55" />
                  ) : (
                    <circle r="3" fill="var(--ink)" />
                  )}
                  <text
                    y="-15"
                    textAnchor="middle"
                    fontFamily="JetBrains Mono"
                    fontWeight="700"
                    fontSize="6"
                    fill="var(--ink)"
                    letterSpacing="0.5"
                  >
                    DAY {i + 1}
                  </text>
                </g>
              );
            })}

            {/* The moving raft glyph — sits ahead of the active stop */}
            <g
              transform={`translate(${boatPos.x}, ${boatPos.y})`}
              style={{ transition: "transform 0.55s cubic-bezier(.7,.2,.3,.9)" }}
            >
              <g transform="translate(0, -22)">
                <ellipse cx="0" cy="0" rx="10" ry="2.5" fill="var(--ink)"/>
                <ellipse cx="0" cy="-1.5" rx="9" ry="2" fill="var(--mustard)"/>
                <line x1="-7" y1="-1" x2="-10" y2="-6" stroke="var(--ink)" strokeWidth="1.2" strokeLinecap="round"/>
                <line x1="7"  y1="-1" x2="10"  y2="-6" stroke="var(--ink)" strokeWidth="1.2" strokeLinecap="round"/>
                <rect x="-1" y="-4" width="2" height="3" fill="var(--ink)" />
                <path d="M 0 -7 L 4 -10 L 0 -10 Z" fill="var(--brick)"/>
              </g>
            </g>
          </svg>

          <div className="river-map-cartouche">
            <b>The Middle Fork</b>
            ≈ {totalMiles} River Miles · 6 Days
          </div>
        </div>

        {/* ── SIDE PANEL ─────────────────────────────────────────── */}
        <div className="river-day-panel">
          <div className="day-num">Day {String(day.day).padStart(2, "0")} · {day.date}</div>
          <div className="day-title">{day.title}</div>
          <div className="day-camp">↳ {day.camp}</div>
          <p className="day-narrative">{day.narrative}</p>

          <div className="day-marks">
            {day.marks.map((m, i) => (
              <span key={i} className={/(Falls|Rapid|Pistol|Redside|Weber|Tappan|Canyon)/i.test(m) ? "hot" : ""}>
                {m}
              </span>
            ))}
          </div>

          <div className="day-stats">
            <div>
              <span className="mono-label">Miles</span>
              <b>{day.miles}</b>
            </div>
            <div>
              <span className="mono-label">Drop</span>
              <b>{day.elev.split(" → ")[0]}<span style={{ fontSize: ".8em", color: "var(--muted)" }}> ft</span></b>
            </div>
            <div>
              <span className="mono-label">Time on water</span>
              <b>{day.runtime}</b>
            </div>
          </div>
        </div>
      </div>

      {/* ── SCRUBBER ─────────────────────────────────────────── */}
      <div className="river-controls">
        <button
          type="button"
          onClick={() => setActive((a) => Math.max(0, a - 1))}
          aria-label="Previous day"
          disabled={active === 0}
          style={{ opacity: active === 0 ? 0.4 : 1 }}
        >‹</button>

        <button
          type="button"
          onClick={() => {
            if (active >= RIVER_DAYS.length - 1) setActive(0);
            setPlaying((p) => !p);
          }}
          aria-label={playing ? "Pause" : "Play"}
          style={{ background: playing ? "var(--ink)" : "var(--paper)", color: playing ? "var(--paper)" : "var(--ink)" }}
        >{playing ? "❚❚" : "▶"}</button>

        <div className="river-scrub">
          <div className="river-scrub-track" />
          <div
            className="river-scrub-fill"
            style={{ width: `${(active / (RIVER_DAYS.length - 1)) * 100}%` }}
          />
          <div className="river-scrub-stops">
            {RIVER_DAYS.map((d, i) => (
              <button
                key={i}
                type="button"
                className="river-scrub-stop"
                data-active={i === active}
                data-past={i < active}
                onClick={() => setActive(i)}
                aria-label={`Jump to Day ${d.day}`}
                title={`Day ${d.day} — ${d.camp}`}
              >
                {d.day}
              </button>
            ))}
          </div>
        </div>

        <button
          type="button"
          onClick={() => setActive((a) => Math.min(RIVER_DAYS.length - 1, a + 1))}
          aria-label="Next day"
          disabled={active === RIVER_DAYS.length - 1}
          style={{ opacity: active === RIVER_DAYS.length - 1 ? 0.4 : 1 }}
        >›</button>
      </div>
    </div>
  );
}

window.RiverMap = RiverMap;
