'use client';

import { useSyncExternalStore } from 'react';

// 3-tier breakpoints aligned with Tailwind:
//   mobile  : < 768px   (sm and below)
//   tablet  : 768-1023  (md)
//   desktop : >= 1024   (lg and up)
//
// Previously the app used a binary `(max-width: 1023.98px)` split, which
// rendered the mobile shell on iPad portrait AND on a half-screen 13"
// Mac browser - neither is really "mobile." The tablet tier fills that
// gap so the desktop shell can render with a hidden-but-accessible
// sidebar at those widths.

export type ViewportTier = 'mobile' | 'tablet' | 'desktop';

const TABLET_QUERY = '(min-width: 768px) and (max-width: 1023.98px)';
const DESKTOP_QUERY = '(min-width: 1024px)';

function subscribeTier(callback: () => void): () => void {
  const mqTablet = window.matchMedia(TABLET_QUERY);
  const mqDesktop = window.matchMedia(DESKTOP_QUERY);
  mqTablet.addEventListener('change', callback);
  mqDesktop.addEventListener('change', callback);
  return () => {
    mqTablet.removeEventListener('change', callback);
    mqDesktop.removeEventListener('change', callback);
  };
}

function getTierSnapshot(): ViewportTier {
  if (window.matchMedia(DESKTOP_QUERY).matches) return 'desktop';
  if (window.matchMedia(TABLET_QUERY).matches) return 'tablet';
  return 'mobile';
}

function getTierServerSnapshot(): ViewportTier {
  // Server has no window - default to desktop so the desktop shell
  // mounts on first paint. Client re-evaluates immediately on hydration
  // (useSyncExternalStore is server-mismatch-safe).
  return 'desktop';
}

/**
 * Returns the active viewport tier. Backed by useSyncExternalStore so
 * render reads stay pure (no useEffect → setState cascade); React
 * Compiler-safe.
 */
export function useViewportTier(): ViewportTier {
  return useSyncExternalStore(subscribeTier, getTierSnapshot, getTierServerSnapshot);
}

// ─── Back-compat alias ──────────────────────────────────────────────────────
// Every existing call site treats "mobile OR tablet" as one bucket (e.g.
// "show short labels", "stack vertically"). Returning `tier !== 'desktop'`
// preserves that behaviour so the tier rollout doesn't have to touch
// dozens of components in lockstep.

const LEGACY_QUERY = '(max-width: 1023.98px)';

function subscribeLegacy(callback: () => void): () => void {
  const mq = window.matchMedia(LEGACY_QUERY);
  mq.addEventListener('change', callback);
  return () => mq.removeEventListener('change', callback);
}

function getLegacySnapshot(): boolean {
  return window.matchMedia(LEGACY_QUERY).matches;
}

function getLegacyServerSnapshot(): boolean {
  return false;
}

/**
 * Returns true when the viewport is below the `lg` Tailwind breakpoint
 * (i.e. mobile OR tablet). Kept as an alias for backwards compatibility
 * with call sites that don't care about the mobile-vs-tablet distinction.
 * New code should prefer `useViewportTier()` for explicit tier checks.
 */
export function useIsMobile(): boolean {
  return useSyncExternalStore(subscribeLegacy, getLegacySnapshot, getLegacyServerSnapshot);
}
