// ============================================================================
// Now / Next bar — always-visible context strip above the tab bar.
// Reads exclusively from useTripState() + useConnector(). Never touches
// data globals directly. Handles all five required states:
//
//   1. loading       — connectors syncing, no data yet
//   2. ok            — today + events + point all resolved
//   3. partial       — day known but no events / no pointId / no POI data
//   4. empty         — pre-trip or post-trip (no "today" at all)
//   5. offline       — data stale + no connection; falls back to SSOT
//
// Tap target adapts to phase:
//   pre-trip  → open checklist (preflight)
//   travel    → open flights
//   in-trip   → open place detail for current point
//   post-trip → open team / memories
// ============================================================================

const { useMemo: nnM } = React;

function parseHHMM(hhmm) {
  const [h, m] = (hhmm || '00:00').split(':').map(Number);
  return h * 60 + (m || 0);
}

function computeNextEvent(today, nowMinUTC) {
  if (!today || !today.events || !today.events.length) {
    return { current: null, next: null, minsToNext: null };
  }
  // Prototype assumes events[].time is local wall-clock. We compare naively.
  const nowLocalMin = parseHHMM(
    `${String(Math.floor((nowMinUTC ?? 0) / 60) % 24).padStart(2, '0')}:${String((nowMinUTC ?? 0) % 60).padStart(2, '0')}`
  );
  let current = null;
  let next = null;
  for (const e of today.events) {
    const t = parseHHMM(e.time);
    if (t <= nowLocalMin) current = e;
    else if (!next) next = e;
  }
  if (!next) next = today.events[today.events.length - 1];
  const minsToNext = next ? Math.max(0, parseHHMM(next.time) - nowLocalMin) : null;
  return { current, next, minsToNext };
}

function formatMinsUntil(mins) {
  if (mins == null) return '';
  if (mins === 0) return 'now';
  if (mins < 60) return `in ${mins}m`;
  const h = Math.floor(mins / 60);
  const m = mins % 60;
  return m === 0 ? `in ${h}h` : `in ${h}h ${m}m`;
}

function formatDaysUntil(days) {
  if (days == null) return '';
  if (days === 0) return 'today';
  if (days === 1) return 'tomorrow';
  return `in ${days} days`;
}

// ---- Phase-specific content resolvers -------------------------------------
// Each resolver returns the same shape so the bar renders uniformly.
// { variant, leftEyebrow, leftTitle, rightEyebrow, rightTitle, action }

function resolvePreTripContent(state) {
  const days = state.daysToStart;
  return {
    variant: 'pre-trip',
    leftEyebrow: 'COUNTDOWN',
    leftTitle: formatDaysUntil(days),
    rightEyebrow: 'NEXT',
    rightTitle: 'Pre-flight tasks',
    action: { screen: 'checklist' },
  };
}

function resolveTravelDayContent(state) {
  const today = state.today;
  const { next, minsToNext } = computeNextEvent(today, state.nowMin);
  if (!next) {
    return {
      variant: 'travel-day',
      leftEyebrow: `DAY ${today?.n ?? '—'}`,
      leftTitle: today?.title || 'Travel day',
      rightEyebrow: 'STATUS',
      rightTitle: 'En route',
      action: { screen: 'flights' },
    };
  }
  return {
    variant: 'travel-day',
    leftEyebrow: `DAY ${today?.n ?? '—'} · TRAVEL`,
    leftTitle: today?.title || 'Travel day',
    rightEyebrow: next.time + (minsToNext != null && minsToNext < 240 ? ` · ${formatMinsUntil(minsToNext)}` : ''),
    rightTitle: next.title,
    action: { screen: 'flights' },
  };
}

function resolveInTripContent(state) {
  const today = state.today;
  if (!today) return resolveEmptyContent();

  const { next, minsToNext } = computeNextEvent(today, state.nowMin);
  const pointId = today.pointIds && today.pointIds[0];
  const point = pointId ? (window.POINTS || {})[pointId] : null;

  return {
    variant: 'in-trip',
    leftEyebrow: `DAY ${today.n}`,
    leftTitle: point ? (point.shortName || point.name) : (today.title || '—'),
    rightEyebrow: next
      ? next.time + (minsToNext != null && minsToNext < 240 ? ` · ${formatMinsUntil(minsToNext)}` : '')
      : 'END OF DAY',
    rightTitle: next ? next.title : 'Wrap up',
    action: pointId ? { screen: 'place', pointId } : { screen: 'map' },
    // partial flag — used for subtle styling
    partial: !point || !today.events?.length,
  };
}

function resolvePostTripContent() {
  return {
    variant: 'post-trip',
    leftEyebrow: 'TRIP COMPLETE',
    leftTitle: 'Memories · 12 days',
    rightEyebrow: 'BROWSE',
    rightTitle: 'Team album',
    action: { screen: 'team' },
  };
}

function resolveEmptyContent() {
  return {
    variant: 'empty',
    leftEyebrow: 'TRIP',
    leftTitle: 'No active day',
    rightEyebrow: '',
    rightTitle: 'Open map',
    action: { screen: 'map' },
  };
}

// ---- Main component -------------------------------------------------------
function NowNextBar() {
  const nav = useNav();
  const state = useTripState();
  const ssot = useConnector('ssot');
  const network = state.network;

  const content = nnM(() => {
    if (!window.DAYS || !window.DAYS.length) return null; // nothing to show at all
    switch (state.phase) {
      case 'pre-trip':   return resolvePreTripContent(state);
      case 'travel-day': return resolveTravelDayContent(state);
      case 'in-trip':    return resolveInTripContent(state);
      case 'post-trip':  return resolvePostTripContent();
      default:           return resolveEmptyContent();
    }
  }, [state.phase, state.today, state.daysToStart, state.nowMin]);

  // Loading state: SSOT not ready yet — show skeleton bar
  if (ssot.status === 'loading' || !content) {
    return (
      <div className="now-next nn-skeleton" aria-busy="true">
        <div className="nn-left">
          <div className="nn-dot"><div className="nn-dot-core" style={{ background: 'var(--ink-4)' }} /></div>
          <div className="nn-now">
            <div className="nn-eyebrow">SYNCING</div>
            <div className="nn-title nn-sk-line" />
          </div>
        </div>
        <div className="nn-arrow">→</div>
        <div className="nn-right">
          <div className="nn-eyebrow">—</div>
          <div className="nn-title nn-sk-line" />
        </div>
      </div>
    );
  }

  // Offline indicator — overlayed as a small pill, doesn't suppress the bar
  const isOffline = network && network.online === false;

  return (
    <button
      className={`now-next nn-v-${content.variant} ${content.partial ? 'nn-partial' : ''} ${isOffline ? 'nn-offline' : ''}`}
      onClick={() => content.action && nav.push(content.action)}
      aria-label={`${content.leftEyebrow} ${content.leftTitle}. Next: ${content.rightTitle}`}
    >
      <div className="nn-left">
        <div className="nn-dot">
          {content.variant === 'in-trip' && <div className="nn-dot-pulse" />}
          <div className="nn-dot-core" />
        </div>
        <div className="nn-now">
          <div className="nn-eyebrow">{content.leftEyebrow}</div>
          <div className="nn-title">{content.leftTitle}</div>
        </div>
      </div>

      <div className="nn-arrow">→</div>

      <div className="nn-right">
        <div className="nn-eyebrow">{content.rightEyebrow || ' '}</div>
        <div className="nn-title nn-next-title">{content.rightTitle}</div>
      </div>

      {isOffline && (
        <div className="nn-offline-pill" title="Offline · showing cached data">
          OFFLINE
        </div>
      )}
    </button>
  );
}

window.NowNextBar = NowNextBar;
