/* nav-screens.jsx — Route selection + Active navigation. Uses shared from window. */

function Stat({ Icon, children }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 13.5, fontWeight: 600, color: 'var(--muted)' }}>
      <Icon size={17} style={{ color: 'var(--faint)' }} /> {children}
    </span>
  );
}

// short labels for the route-composition legend (same colors the map draws + the filter legend).
const CAT_LEGEND_LABEL = {
  bikelane: 'Велоалея', bikelane_shared: 'Споделена алея', comfort: 'Удобна улица',
  rough: 'Неасфалтирано', sidewalk: 'Широк тротоар', street: 'Улица',
};
function catVarName(cat) {
  if (!cat || cat === 'street') return 'route-street';
  const c = window.VR_COMMUNITY && window.VR_COMMUNITY.cats && window.VR_COMMUNITY.cats[cat];
  return (c && c.color) || 'route-street';
}
// Legend for the SELECTED route: the infrastructure types it rides on, biggest share first.
// Lets the rider read what to expect (bike lane vs. plain street) before starting.
function RouteLegend({ pattern }) {
  if (!pattern || !pattern.length) return null;
  const share = {};
  pattern.forEach((p) => { share[p.cat] = (share[p.cat] || 0) + p.frac; });
  const cats = Object.keys(share).filter((c) => share[c] > 0.04).sort((a, b) => share[b] - share[a]);
  if (cats.length < 2) return null;   // a single type → nothing to compare
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px 12px', padding: '2px 20px 8px' }}>
      {cats.map((c) => (
        <span key={c} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 600, color: 'var(--muted)' }}>
          <span style={{ width: 16, height: 4, borderRadius: 3, background: `var(--${catVarName(c)})`, flexShrink: 0 }} />
          {CAT_LEGEND_LABEL[c] || c} <span style={{ color: 'var(--faint)' }}>{Math.round(share[c] * 100)}%</span>
        </span>
      ))}
    </div>
  );
}

function RouteSelectScreen({ theme, go, back, routes, selected, onSelect, destInfo, originName, originAt, destAt }) {
  const { glassStyle, RoundBtn, ZoomControl, SafetyChip, IconBack, IconBike, IconClock,
    IconElevation, IconCar, IconLeaf, IconNavArrow, IconShield, IconChevDown } = window;
  const sel = selected;
  const setSel = onSelect;
  const ROUTES = routes;
  const [collapsed, setCollapsed] = React.useState(false);
  const selRoute = ROUTES.find((r) => r.id === sel) || ROUTES[0];

  // favourite-this-route + recent-trip recording
  const fromName = originName || 'Моето местоположение';
  const toName = (destInfo && destInfo.name) || 'Дестинация';
  const savedRoutes = window.useSavedRoutes ? window.useSavedRoutes() : [];
  const routeId = window.SavedRoutes ? window.SavedRoutes.routeId(fromName, toName) : '';
  const isFav = savedRoutes.some((x) => x.id === routeId);
  const toggleFav = () => {
    if (!window.SavedRoutes) return;
    window.SavedRoutes.toggle({ id: routeId, from: fromName, to: toName, fromAt: originAt || null, toAt: destAt || null,
      level: selRoute.level, score: selRoute.score, dist: selRoute.dist, time: selRoute.time });
  };
  const startNav = () => {
    // iOS needs the compass permission asked from inside the user gesture; ignore elsewhere.
    try { if (window.DeviceOrientationEvent && DeviceOrientationEvent.requestPermission) DeviceOrientationEvent.requestPermission().catch(() => {}); } catch (e) {}
    go('nav');   // the trip is recorded on arrival/end (app.endNav), reflecting the real ride
  };

  return (
    // pointerEvents:none lets map gestures (pan/zoom) pass through the empty area; each
    // interactive child re-enables pointerEvents so the map stays explorable behind the sheet.
    <div style={{ position: 'absolute', inset: 0, zIndex: 20, pointerEvents: 'none' }}>
      {/* header destination pill */}
      <div style={{ position: 'absolute', top: 60, left: 14, right: 14, zIndex: 25, pointerEvents: 'auto',
        display: 'flex', alignItems: 'center', gap: 10, height: 54, borderRadius: 18,
        padding: '0 16px 0 8px', boxShadow: 'var(--shadow-lg)', ...glassStyle(theme, true) }}>
        <button onClick={back} className="tap" style={{ background: 'none', border: 'none', color: 'var(--text)', cursor: 'pointer', padding: 6 }}>
          <IconBack size={24} />
        </button>
        <span style={{ flex: 1, lineHeight: 1.15, minWidth: 0 }}>
          <span style={{ display: 'block', fontSize: 16, fontWeight: 700, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{destInfo ? destInfo.name : 'Народен театър'}</span>
          <span style={{ display: 'block', fontSize: 12.5, color: 'var(--muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{['от ' + (originName || 'Моето местоположение'), '3 маршрута'].join(' · ')}</span>
        </span>
        <button onClick={toggleFav} className="tap" aria-label="Запази маршрут" style={{ flexShrink: 0, width: 38, height: 38, borderRadius: 19, border: 'none', cursor: 'pointer', background: isFav ? 'color-mix(in oklch, var(--brand) 16%, transparent)' : 'var(--surface-2)', color: isFav ? 'var(--brand)' : 'var(--muted)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill={isFav ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth="1.8" strokeLinejoin="round"><path d="M12 4l2.4 5 5.6.6-4.2 3.8 1.2 5.6L12 16.8 7 19l1.2-5.6L4 9.6 9.6 9 12 4z"/></svg>
        </button>
      </div>

      {/* zoom control */}
      <div style={{ position: 'absolute', right: 14, top: 128, zIndex: 25, pointerEvents: 'auto' }}>
        <ZoomControl theme={theme} />
      </div>

      {/* bottom sheet */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 26, pointerEvents: 'auto',
        borderRadius: '28px 28px 0 0', paddingBottom: 30,
        boxShadow: 'var(--shadow-lg)', ...glassStyle(theme, true),
        display: 'flex', flexDirection: 'column', maxHeight: 560,
      }}>
        <div onClick={() => setCollapsed((c) => !c)} className="tap" style={{ cursor: 'pointer', flexShrink: 0 }}>
          <div style={{ width: 40, height: 5, borderRadius: 9, background: 'var(--hairline)', margin: '8px auto 2px' }} />
          <div style={{ padding: '4px 20px 6px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <h2 style={{ margin: 0, fontSize: 21, fontWeight: 800, color: 'var(--text)' }}>Изберете маршрут</h2>
            <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--muted)' }}>{collapsed ? `${selRoute.tag} · ${selRoute.time} мин` : 'с велосипед'}</span>
              <IconChevDown size={20} style={{ color: 'var(--muted)', transform: collapsed ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
            </span>
          </div>
        </div>

        {!collapsed && <RouteLegend pattern={selRoute.catPattern} />}

        <div className="noscroll" style={{ display: collapsed ? 'none' : 'flex', overflowY: 'auto', padding: '8px 14px 4px', flexDirection: 'column', gap: 10 }}>
          {ROUTES.map((r) => {
            const on = sel === r.id;
            return (
              <button key={r.id} onClick={() => setSel(r.id)} className="tap" style={{
                textAlign: 'left', cursor: 'pointer', borderRadius: 18, padding: '13px 15px',
                background: on ? 'color-mix(in oklch, var(--brand) 8%, var(--surface))' : 'var(--surface)',
                border: on ? '2px solid var(--brand)' : '2px solid transparent',
                boxShadow: on ? 'none' : 'var(--shadow)', color: 'var(--text)',
                transition: 'border-color .15s, background .15s',
              }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 10px',
                    borderRadius: 999, fontSize: 12.5, fontWeight: 700,
                    background: r.level === 'safe' ? 'color-mix(in oklch, var(--safe) 16%, transparent)' : 'color-mix(in oklch, var(--moderate) 18%, transparent)',
                    color: r.level === 'safe' ? 'var(--safe)' : 'var(--moderate)' }}>
                    {r.id === 'scenic' ? <IconLeaf size={15} /> : <IconBike size={15} />} {r.tag}
                  </span>
                  <span style={{ flex: 1 }} />
                  <span style={{ fontSize: 22, fontWeight: 800, lineHeight: 1 }}>{r.time}<span style={{ fontSize: 13, fontWeight: 600, color: 'var(--muted)' }}> мин</span></span>
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap', marginBottom: 8 }}>
                  <SafetyChip level={r.level} score={r.score} />
                  <Stat Icon={IconBike}>{r.lanes} велоалеи</Stat>
                  {r.elev && <Stat Icon={IconElevation}>{r.elev}</Stat>}
                  <Stat Icon={IconCar}>трафик {r.traffic}</Stat>
                </div>
                <div style={{ fontSize: 13, color: 'var(--muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ color: 'var(--faint)' }}>{r.dist}</span> · {r.note}
                </div>
                <div style={{ marginTop: 7, fontSize: 12.5, fontWeight: 700, display: 'flex', alignItems: 'center', gap: 5,
                  color: r.id === 'fast' ? 'var(--danger)' : 'var(--safe)' }}>
                  {r.id === 'fast'
                    ? <><IconCar size={15} /> {r.avoids} докладвани опасности по пътя</>
                    : <><IconShield size={15} /> избягва {r.avoids} докладвани опасности</>}
                </div>
              </button>
            );
          })}
        </div>

        {collapsed && (
          <div style={{ padding: '2px 16px 0', display: 'flex', alignItems: 'center', gap: 12 }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '5px 11px', borderRadius: 999, fontSize: 13, fontWeight: 700,
              background: selRoute.level === 'safe' ? 'color-mix(in oklch, var(--safe) 16%, transparent)' : 'color-mix(in oklch, var(--moderate) 18%, transparent)',
              color: selRoute.level === 'safe' ? 'var(--safe)' : 'var(--moderate)' }}>
              {selRoute.id === 'scenic' ? <IconLeaf size={15} /> : <IconBike size={15} />} {selRoute.tag}
            </span>
            <SafetyChip level={selRoute.level} score={selRoute.score} />
            <span style={{ marginLeft: 'auto', fontSize: 18, fontWeight: 800 }}>{selRoute.time}<span style={{ fontSize: 12, fontWeight: 600, color: 'var(--muted)' }}> мин</span></span>
          </div>
        )}

        <div style={{ padding: '12px 16px 0' }}>
          <button onClick={startNav} className="tap" style={{
            width: '100%', height: 56, borderRadius: 18, border: 'none', cursor: 'pointer',
            background: 'var(--brand)', color: '#fff', fontSize: 18, fontWeight: 800,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
            boxShadow: '0 8px 22px color-mix(in oklch, var(--brand) 40%, transparent)',
          }}>
            <IconNavArrow size={21} /> Старт
          </button>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// ACTIVE NAVIGATION — driven by the live NavEngine (real GPS / injected positions).
// The engine projects the rider onto the route, advances the maneuver, counts down to the
// next turn, recomputes ETA, reroutes when off-course, and speaks instructions.
// ============================================================
function ActiveNavScreen({ theme, go, route, selected, onRoute, onEnd, voice, openReport }) {
  const { glassStyle, IconSound, IconWarn, IconNavArrow, IconLocateDot, IconClose } = window;
  const riding = theme === 'riding';
  const E = window.NavEngine;
  const [nav, setNav] = React.useState(() => (E ? E.getState() : null));
  const [voiceOn, setVoiceOn] = React.useState(voice !== false);
  const endedRef = React.useRef(false);
  const finish = () => { if (!endedRef.current) { endedRef.current = true; if (onEnd) onEnd(); else go('home'); } };

  React.useEffect(() => {
    if (!E || !route) return;
    const off = E.subscribe(() => setNav(E.getState()));
    E.start(route, selected, {
      dest: route.dest, voice: voice !== false,
      onRoute: (r) => onRoute && onRoute(r),
      onArrive: finish,
    });
    setNav(E.getState());
    return () => { off(); E.stop(); };
  }, []);  // eslint-disable-line — start once per nav session

  const toggleVoice = () => { const v = !voiceOn; setVoiceOn(v); if (E) E.setVoice(v); };

  if (!nav) return null;
  const step = nav.step || { icon: 'IconNavArrow', text: 'Тръгнете', street: '' };
  const ManIcon = window[step.icon] || IconNavArrow;
  const next = nav.nextStep;
  const NextIcon = next ? (window[next.icon] || IconNavArrow) : null;
  const rerouting = nav.status === 'rerouting';
  const arrived = nav.status === 'arrived';

  const bannerH = riding ? 150 : 122;
  const instrSize = riding ? 34 : 28;
  const distSize = riding ? 46 : 38;

  return (
    // pointerEvents:none lets the map underneath receive pan/zoom/drag during navigation; each
    // interactive child (FAB, sheet, report) re-enables pointerEvents. Without this the full-screen
    // overlay swallowed every gesture, freezing the map and hiding the locate button.
    <div style={{ position: 'absolute', inset: 0, zIndex: 20, pointerEvents: 'none' }}>
      {/* maneuver banner (or a recalculating state) */}
      <div style={{
        position: 'absolute', top: 52, left: 12, right: 12, zIndex: 27,
        minHeight: bannerH, borderRadius: 24, padding: riding ? '18px 20px' : '16px 18px',
        background: rerouting
          ? 'linear-gradient(150deg, var(--moderate), color-mix(in oklch, var(--moderate) 70%, #000))'
          : 'linear-gradient(150deg, var(--navline), color-mix(in oklch, var(--navline) 72%, #000))',
        color: '#fff', display: 'flex', alignItems: 'center', gap: 16,
        boxShadow: '0 10px 30px color-mix(in oklch, var(--navline) 40%, transparent)',
      }}>
        {rerouting ? (
          <React.Fragment>
            <span className="vr-spin" style={{ width: 30, height: 30, borderRadius: '50%', border: '4px solid rgba(255,255,255,.4)', borderTopColor: '#fff', flexShrink: 0 }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 22, fontWeight: 800 }}>Преизчисляване…</div>
              <div style={{ fontSize: 14.5, fontWeight: 500, opacity: 0.9 }}>Връщане към маршрута</div>
            </div>
          </React.Fragment>
        ) : (
          <React.Fragment>
            <ManIcon size={riding ? 64 : 54} sw={2.4} style={{ color: '#fff', flexShrink: 0 }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: distSize, fontWeight: 800, lineHeight: 1, letterSpacing: -0.5 }}>
                {arrived ? '0' : nav.distToManeuver}<span style={{ fontSize: distSize * 0.42, fontWeight: 700 }}> м</span>
              </div>
              <div style={{ fontSize: instrSize * 0.62, fontWeight: 700, marginTop: 4, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{step.text}</div>
              {step.street ? <div style={{ fontSize: 14.5, fontWeight: 500, opacity: 0.85, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>по {step.street}</div> : null}
            </div>
          </React.Fragment>
        )}
      </div>

      {/* "then" strip */}
      {!rerouting && next && NextIcon && (
        <div style={{
          position: 'absolute', top: 52 + bannerH + 8, left: 24, right: 24, zIndex: 26,
          height: 38, borderRadius: 12, padding: '0 14px',
          display: 'flex', alignItems: 'center', gap: 8,
          background: theme === 'light' ? 'rgba(255,255,255,0.9)' : 'rgba(20,24,32,0.9)',
          backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
          boxShadow: 'var(--shadow)', color: 'var(--muted)', fontSize: 13.5, fontWeight: 600,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          После <NextIcon size={18} style={{ color: 'var(--navline)', flexShrink: 0 }} /> {next.text.toLowerCase()}{next.street ? ' по ' + next.street : ''}
        </div>
      )}

      {/* persistent locate / recenter FAB — always tappable; re-centers on the puck and
          re-engages follow. When already following it shows a subtler "centered" state. */}
      <button onClick={() => E && E.recenter()} className="tap" aria-label="Покажи моето местоположение" style={{
        position: 'absolute', left: '50%', transform: 'translateX(-50%)', bottom: 150, zIndex: 28, pointerEvents: 'auto',
        height: 42, padding: '0 18px', borderRadius: 21, border: 'none', cursor: 'pointer',
        background: nav.follow ? 'var(--surface)' : 'var(--brand)',
        color: nav.follow ? 'var(--brand)' : '#fff', fontSize: 14.5, fontWeight: 700,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7,
        boxShadow: nav.follow ? 'var(--shadow-lg)' : '0 8px 22px color-mix(in oklch, var(--brand) 40%, transparent)',
      }}>{nav.follow
        ? <>{React.createElement(IconLocateDot || IconNavArrow, { size: 18 })} Следва те</>
        : <><IconNavArrow size={18} /> Центрирай</>}</button>

      {/* bottom sheet */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 27, pointerEvents: 'auto',
        borderRadius: '26px 26px 0 0', padding: riding ? '18px 18px 30px' : '16px 18px 30px',
        boxShadow: 'var(--shadow-lg)', ...glassStyle(theme, true),
      }}>
        {arrived ? (
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: riding ? 26 : 23, fontWeight: 800, color: 'var(--safe)', lineHeight: 1.1 }}>Пристигнахте 🎉</div>
              <div style={{ fontSize: 14.5, color: 'var(--muted)', fontWeight: 600, marginTop: 4 }}>Приятен ден!</div>
            </div>
            <button onClick={finish} className="tap" style={{
              height: 48, padding: '0 24px', borderRadius: 24, border: 'none', cursor: 'pointer',
              background: 'var(--brand)', color: '#fff', fontSize: 16, fontWeight: 800,
            }}>Готово</button>
          </div>
        ) : (
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{ flex: 1 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                <span style={{ fontSize: riding ? 34 : 30, fontWeight: 800, color: 'var(--safe)', lineHeight: 1 }}>{nav.etaMin} мин</span>
              </div>
              <div style={{ fontSize: 14.5, color: 'var(--muted)', fontWeight: 600, marginTop: 3 }}>{nav.distRemainingKm} · пристигане {nav.arrival}</div>
            </div>
            {/* speed */}
            <div style={{ textAlign: 'center', minWidth: 64 }}>
              <div style={{ fontSize: riding ? 30 : 26, fontWeight: 800, lineHeight: 1, color: 'var(--text)' }}>{nav.speedKmh}</div>
              <div style={{ fontSize: 11.5, color: 'var(--faint)', fontWeight: 700, letterSpacing: 0.3 }}>км/ч</div>
            </div>
            <button onClick={toggleVoice} className="tap" aria-label="Глас" style={{
              width: 48, height: 48, borderRadius: 24, border: 'none', cursor: 'pointer',
              background: voiceOn ? 'color-mix(in oklch, var(--brand) 16%, transparent)' : 'var(--surface-2)',
              color: voiceOn ? 'var(--brand)' : 'var(--faint)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}><IconSound size={23} /></button>
            <button onClick={finish} className="tap" style={{
              height: 48, padding: '0 20px', borderRadius: 24, border: 'none', cursor: 'pointer',
              background: 'var(--danger)', color: '#fff', fontSize: 16, fontWeight: 800,
            }}>Край</button>
          </div>
        )}
      </div>

      {/* report FAB */}
      {!arrived && (
        <button onClick={openReport} className="tap" style={{
          position: 'absolute', right: 14, top: 52 + bannerH + 56, zIndex: 26, pointerEvents: 'auto',
          width: 50, height: 50, borderRadius: 25, border: 'none', cursor: 'pointer',
          background: 'var(--surface)', color: 'var(--danger)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: 'var(--shadow-lg)',
        }}><IconWarn size={24} /></button>
      )}
    </div>
  );
}

// Shown while live OSRM routing is computed for the chosen endpoints (route === null).
// Same pointerEvents pattern so the map underneath stays explorable while it loads.
function RouteLoading({ theme, back, destName }) {
  const { glassStyle, IconBack } = window;
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 20, pointerEvents: 'none' }}>
      <div style={{ position: 'absolute', top: 60, left: 14, right: 14, zIndex: 25, pointerEvents: 'auto',
        display: 'flex', alignItems: 'center', gap: 10, height: 54, borderRadius: 18,
        padding: '0 16px 0 8px', boxShadow: 'var(--shadow-lg)', ...glassStyle(theme, true) }}>
        <button onClick={back} className="tap" style={{ background: 'none', border: 'none', color: 'var(--text)', cursor: 'pointer', padding: 6 }}>
          <IconBack size={24} />
        </button>
        <span style={{ flex: 1, fontSize: 15, fontWeight: 600, color: 'var(--muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {destName ? 'Маршрути до ' + destName : 'Изчисляване на маршрути'}…
        </span>
      </div>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 26, pointerEvents: 'auto',
        borderRadius: '28px 28px 0 0', padding: '30px 20px 46px', boxShadow: 'var(--shadow-lg)', ...glassStyle(theme, true),
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
        <span className="vr-spin" style={{ width: 22, height: 22, borderRadius: '50%', border: '3px solid var(--hairline)', borderTopColor: 'var(--brand)' }} />
        <span style={{ fontSize: 16, fontWeight: 700, color: 'var(--text)' }}>Търсене на безопасни маршрути…</span>
      </div>
    </div>
  );
}

Object.assign(window, { RouteSelectScreen, ActiveNavScreen, RouteLoading });
