import { useMediaQuery } from 'usehooks-ts';

import {
  TAILWIND_2XS_MIN_WIDTH,
  TAILWIND_LARGE_MIN_WIDTH,
  TAILWIND_MEDIUM_MIN_WIDTH,
  TAILWIND_SMALL_MIN_WIDTH,
  TAILWIND_XL_MIN_WIDTH,
  TAILWIND_XS_MIN_WIDTH,
  TAILWIND_XXL_MIN_WIDTH,
} from '@/utils/constants';

/**
 * Min-width is extra extra small (tiny phone+)
 */
export function useBreakpointXxs() {
  return useBreakpoint(TAILWIND_2XS_MIN_WIDTH);
}

/**
 * Min-width is extra small (small mobile+)
 */
export function useBreakpointXs() {
  return useBreakpoint(TAILWIND_XS_MIN_WIDTH);
}

/**
 * Min-width is small (mobile+)
 */
export function useBreakpointSm() {
  return useBreakpoint(TAILWIND_SMALL_MIN_WIDTH);
}

/**
 * Min-width is medium (tablet+)
 */
export function useBreakpointMd() {
  return useBreakpoint(TAILWIND_MEDIUM_MIN_WIDTH);
}

/**
 * Min-width is large (desktop+)
 */
export function useBreakpointLg() {
  return useBreakpoint(TAILWIND_LARGE_MIN_WIDTH);
}

/**
 * Min-width is extra large
 */
export function useBreakpointXl() {
  return useBreakpoint(TAILWIND_XL_MIN_WIDTH);
}

/**
 * Min-width is extra EXTRA large
 */
export function useBreakpointXxl() {
  return useBreakpoint(TAILWIND_XXL_MIN_WIDTH);
}

/**
 * Determines whether the screen satisfies a given breakpoint as specified by a min-width
 *
 * We define these in terms of min-width (and not max-width) to align with the behavior of the
 * Tailwind breakpoints, which assumes mobile devices with small screens as the default.
 *
 * Note that breakpoints include the named size and anything larger, so a "medium" size used for
 * "tablet" implicitly means "desktop" as well! To enforce a max-width, negate the next larger
 * breakpoint.
 *
 * For example, a tablet-only breakpoint that EXCLUDES desktop would be require this:
 *
 * ```
 * const isTablet = useBreakpointMd();
 * const isDesktop = useBreakpointLg();
 * const isStrictlyTablet = isTablet && !isDesktop;
 * ```
 */
export default function useBreakpoint(
  minWidth: number,
  initializeWithValue: boolean = false
) {
  // Always call the hook first
  const result = useMediaQuery(`(min-width: ${minWidth}px)`, {
    initializeWithValue:
      typeof window === 'undefined' ? false : initializeWithValue,
  });

  // During SSR, return false to avoid hydration mismatches
  if (typeof window === 'undefined') {
    return false;
  }

  return result;
}
