// iceland-map.jsx — fullscreen interactive trip map on real dark tiles (Leaflet).
// Needs GL, Ph, KickBadge, MAP, L (Leaflet), window.TRIP. Exports FullMapScreen, MiniMap.
const { useState: useStateM, useEffect: useEffectM, useRef: useRefM } = React;

const TILES = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
const TILE_OPTS = { subdomains: 'abcd', maxZoom: 18, attribution: '© OpenStreetMap, © CARTO' };
const GLA = '#5cb8e8';
const ll = id => [MAP.byId[id].lat, MAP.byId[id].lon];

function pinIcon(p, sel, on) {
  return L.divIcon({
    className: 'ice-pin',
    html: `<span class="ice-dot${p.kick ? ' kick' : ''}${sel ? ' sel' : ''}"></span>`,
    iconSize: [16, 16], iconAnchor: [8, 8],
  });
}

// ── Fullscreen map ───────────────────────────────────────────
function FullMapScreen({ onClose, onOpenDay }) {
  const [day, setDay] = useStateM(null);
  const [pinId, setPinId] = useStateM(null);
  const elRef = useRefM(null), mapRef = useRefM(null), markRef = useRefM({}), routeRef = useRefM(null);
  const sel = pinId ? MAP.byId[pinId] : null;

  // init map + markers once
  useEffectM(() => {
    const map = L.map(elRef.current, { zoomControl: false, attributionControl: true, scrollWheelZoom: true });
    L.tileLayer(TILES, TILE_OPTS).addTo(map);
    L.control.zoom({ position: 'bottomright' }).addTo(map);
    routeRef.current = L.layerGroup().addTo(map);
    MAP.pts.forEach(p => {
      const m = L.marker([p.lat, p.lon], { icon: pinIcon(p, false, true) }).addTo(map);
      m.on('click', () => setPinId(p.id));
      m.bindTooltip(p.name, { permanent: true, direction: 'bottom', className: 'ice-tip', offset: [0, 6] });
      markRef.current[p.id] = m;
    });
    map.fitBounds(L.latLngBounds(MAP.pts.map(p => [p.lat, p.lon])), { padding: [55, 55], maxZoom: 9 });
    mapRef.current = map;
    const t = setTimeout(() => map.invalidateSize(), 250);
    const ro = new ResizeObserver(() => map.invalidateSize());
    ro.observe(elRef.current);
    return () => { clearTimeout(t); ro.disconnect(); map.remove(); };
  }, []);

  // restyle markers + routes on day/selection change
  useEffectM(() => {
    const map = mapRef.current; if (!map) return;
    const active = day == null ? null : TRIP.legs[day];
    MAP.pts.forEach(p => {
      const on = active ? active.includes(p.id) : true;
      const m = markRef.current[p.id];
      m.setIcon(pinIcon(p, pinId === p.id, on));
      m.setOpacity(on ? 1 : 0.35);
      m.setZIndexOffset(pinId === p.id ? 1000 : (on ? 200 : 0));
      const tip = m.getTooltip && m.getTooltip();
      const el = tip && tip.getElement && tip.getElement();
      if (el) { el.style.display = (day == null || on) ? '' : 'none'; el.classList.toggle('on', on && (p.kick || pinId === p.id)); }
    });
    routeRef.current.clearLayers();
    TRIP.legs.forEach((leg, i) => {
      const pts = leg.map(ll);
      if (day == null) L.polyline(pts, { color: '#9fb6c6', opacity: 0.4, weight: 1.5, dashArray: '4 6' }).addTo(routeRef.current);
      else if (i === day) L.polyline(pts, { color: GLA, opacity: 0.95, weight: 4 }).addTo(routeRef.current);
      else L.polyline(pts, { color: '#7f8b96', opacity: 0.12, weight: 1, dashArray: '3 6' }).addTo(routeRef.current);
    });
    const fitPts = active ? active.map(ll) : MAP.pts.map(p => [p.lat, p.lon]);
    map.fitBounds(L.latLngBounds(fitPts), { padding: [60, 70], maxZoom: active ? 10 : 9, animate: true });
  }, [day, pinId]);

  const chips = [{ k: null, label: 'Hele lus' }, ...TRIP.days.map((d, i) => ({ k: i, label: `${d.dow} ${d.date.split(' ')[0]}` }))];

  return (
    <div style={{ position: 'absolute', inset: 0, background: GL.bg, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      {/* Map fills everything */}
      <div ref={elRef} style={{ position: 'absolute', inset: 0, zIndex: 1 }} />

      {/* top gradient for header legibility */}
      <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 150, zIndex: 2, pointerEvents: 'none',
        background: 'linear-gradient(180deg, rgba(11,12,15,0.92) 0%, rgba(11,12,15,0.5) 55%, transparent 100%)' }} />

      {/* Header */}
      <div style={{ position: 'relative', zIndex: 5, padding: '16px 16px 10px' }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
          <button onClick={onClose} aria-label="Sluiten" style={{
            width: 40, height: 40, borderRadius: 12, flexShrink: 0, cursor: 'pointer',
            background: 'rgba(21,23,28,0.85)', border: `1px solid ${GL.line}`, color: GL.text,
            display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 0, backdropFilter: 'blur(12px)' }}>
            <svg width="15" height="15" viewBox="0 0 15 15"><path d="M2 2l11 11M13 2L2 13" stroke={GL.text} strokeWidth="2" strokeLinecap="round"/></svg>
          </button>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: GL.display, fontSize: 24, letterSpacing: 0.5, textTransform: 'uppercase', color: GL.text, lineHeight: 1, textShadow: '0 2px 12px rgba(0,0,0,0.6)' }}>Reiskaart</div>
            <div style={{ fontFamily: GL.mono, fontSize: 10, letterSpacing: 1, color: 'rgba(255,255,255,0.7)', marginTop: 4, textShadow: '0 1px 6px rgba(0,0,0,0.8)' }}>TIK EEN PUNT VOOR DETAILS · {MAP.pts.length} STOPS</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 7, marginTop: 14, overflowX: 'auto', paddingBottom: 2 }}>
          {chips.map(c => (
            <button key={String(c.k)} onClick={() => { setDay(c.k); setPinId(null); }} style={{
              flexShrink: 0, fontFamily: GL.mono, fontSize: 11, letterSpacing: 0.5, padding: '8px 13px', borderRadius: 9, cursor: 'pointer',
              background: day === c.k ? GLA : 'rgba(21,23,28,0.85)', color: day === c.k ? GL.bg : GL.mut, backdropFilter: 'blur(12px)',
              border: `1px solid ${day === c.k ? GLA : GL.line}`, fontWeight: day === c.k ? 700 : 400 }}>{c.label}</button>
          ))}
        </div>
      </div>

      <div style={{ flex: 1 }} />

      {/* Waypoint sheet */}
      {sel && (
        <React.Fragment>
          <div onClick={() => setPinId(null)} style={{ position: 'absolute', inset: 0, zIndex: 14, background: 'rgba(0,0,0,0.45)' }} />
          <div key={sel.id} style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 15,
            background: GL.surfaceSolid, borderTopLeftRadius: 22, borderTopRightRadius: 22,
            border: `1px solid ${GL.line}`, borderBottom: 'none', overflow: 'hidden',
            boxShadow: '0 -12px 40px rgba(0,0,0,0.5)', animation: 'wpUp .26s cubic-bezier(.2,.8,.2,1)' }}>
            <div style={{ display: 'flex', justifyContent: 'center', padding: '9px 0 3px' }}>
              <div style={{ width: 38, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.25)' }} />
            </div>
            <div style={{ position: 'relative', margin: '6px 14px 0', borderRadius: 14, overflow: 'hidden' }}>
              <Ph label={sel.hero} hue={sel.hue} h={150} src={sel.img} />
              <div style={{ position: 'absolute', top: 11, left: 11, display: 'flex', gap: 7, alignItems: 'center' }}>
                <span style={{ fontFamily: GL.mono, fontSize: 10, fontWeight: 700, letterSpacing: 1, color: GL.bg,
                  background: '#fff', padding: '3px 8px', borderRadius: 6 }}>
                  {sel.base ? 'BASIS' : `DAG ${TRIP.days[sel.d].n}`}</span>
                {sel.kick && <KickBadge />}
              </div>
              <button onClick={() => setPinId(null)} style={{ position: 'absolute', top: 9, right: 9, width: 30, height: 30, borderRadius: '50%',
                background: 'rgba(0,0,0,0.5)', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(6px)' }}>
                <svg width="12" height="12" viewBox="0 0 15 15"><path d="M2 2l11 11M13 2L2 13" stroke="#fff" strokeWidth="2" strokeLinecap="round"/></svg>
              </button>
            </div>
            <div style={{ padding: '14px 18px 22px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
                <span style={{ fontFamily: GL.mono, fontSize: 13, color: GL.glacier, fontWeight: 700 }}>{sel.time}</span>
                <span style={{ fontFamily: GL.mono, fontSize: 10, color: GL.faint, letterSpacing: 0.5 }}>{TRIP.days[sel.d].dayName.toUpperCase()} {sel.base ? '' : '· ' + TRIP.days[sel.d].date.toUpperCase()}</span>
              </div>
              <div style={{ fontFamily: GL.display, fontSize: 27, textTransform: 'uppercase', color: GL.text, lineHeight: 1, letterSpacing: 0.4 }}>{sel.name}</div>
              <p style={{ fontFamily: GL.body, fontSize: 14, lineHeight: 1.5, color: GL.mut, margin: '11px 0 0' }}>{sel.desc}</p>
              <button onClick={() => { onOpenDay(sel.d); }} style={{
                marginTop: 16, width: '100%', padding: '13px', borderRadius: 12, cursor: 'pointer',
                fontFamily: GL.mono, fontSize: 12, letterSpacing: 0.5, fontWeight: 700,
                background: GL.glacier, color: GL.bg, border: 'none' }}>
                BEKIJK HELE DAG {TRIP.days[sel.d].n} →
              </button>
            </div>
          </div>
        </React.Fragment>
      )}
      <style>{`@keyframes wpUp{from{transform:translateY(100%)}to{transform:translateY(0)}}`}</style>
    </div>
  );
}

// ── Non-interactive mini preview for the home card ───────────
function MiniMap() {
  const elRef = useRefM(null);
  useEffectM(() => {
    const map = L.map(elRef.current, { zoomControl: false, attributionControl: false, dragging: false,
      scrollWheelZoom: false, doubleClickZoom: false, boxZoom: false, keyboard: false, touchZoom: false, tap: false });
    L.tileLayer(TILES, TILE_OPTS).addTo(map);
    TRIP.legs.forEach(leg => L.polyline(leg.map(ll), { color: GLA, opacity: 0.55, weight: 1.6, dashArray: '3 4' }).addTo(map));
    MAP.pts.forEach(p => L.circleMarker([p.lat, p.lon], { radius: p.kick ? 3.6 : 2.6, stroke: false,
      fillColor: p.kick ? GLA : '#fff', fillOpacity: 0.92 }).addTo(map));
    map.fitBounds(L.latLngBounds(MAP.pts.map(p => [p.lat, p.lon])), { padding: [16, 16] });
    const t = setTimeout(() => map.invalidateSize(), 180);
    const ro = new ResizeObserver(() => map.invalidateSize());
    ro.observe(elRef.current);
    return () => { clearTimeout(t); ro.disconnect(); map.remove(); };
  }, []);
  return <div ref={elRef} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }} />;
}

Object.assign(window, { FullMapScreen, MiniMap });

// ── Compact interactive map for the Routes panel ─────────────
function DayRouteMap({ day }) {
  const elRef = useRefM(null), mapRef = useRefM(null), routeRef = useRefM(null), markRef = useRefM({});
  useEffectM(() => {
    const map = L.map(elRef.current, { zoomControl: false, attributionControl: true, scrollWheelZoom: false });
    L.tileLayer(TILES, TILE_OPTS).addTo(map);
    routeRef.current = L.layerGroup().addTo(map);
    MAP.pts.forEach(p => {
      const m = L.marker([p.lat, p.lon], { icon: pinIcon(p, false, true), interactive: false }).addTo(map);
      markRef.current[p.id] = m;
    });
    map.fitBounds(L.latLngBounds(MAP.pts.map(p => [p.lat, p.lon])), { padding: [30, 30], maxZoom: 9 });
    mapRef.current = map;
    const t = setTimeout(() => map.invalidateSize(), 220);
    const ro = new ResizeObserver(() => map.invalidateSize());
    ro.observe(elRef.current);
    return () => { clearTimeout(t); ro.disconnect(); map.remove(); };
  }, []);
  useEffectM(() => {
    const map = mapRef.current; if (!map) return;
    const active = TRIP.legs[day];
    MAP.pts.forEach(p => {
      const on = active.includes(p.id);
      markRef.current[p.id].setIcon(pinIcon(p, false, on));
      markRef.current[p.id].setOpacity(on ? 1 : 0.3);
    });
    routeRef.current.clearLayers();
    L.polyline(active.map(ll), { color: GLA, opacity: 0.95, weight: 4 }).addTo(routeRef.current);
    map.fitBounds(L.latLngBounds(active.map(ll)), { padding: [34, 34], maxZoom: 10, animate: true });
  }, [day]);
  return <div ref={elRef} style={{ height: 230, borderRadius: 16, overflow: 'hidden', border: `1px solid ${GL.line}` }} />;
}

Object.assign(window, { FullMapScreen, MiniMap, DayRouteMap });
