/**
 * Pure layout-shell visibility rules for the app's bottom UI (mini player
 * stacked over the bottom nav).
 *
 * These rules used to live as inline `$derived` booleans scattered across the
 * root and library `+layout.svelte` files and diverged per platform/route.
 *
 * The overlap bug ("last row hidden behind the nav") is now solved
 * STRUCTURALLY, not by these rules: the bottom UI is rendered as an in-flow
 * flex child below the scroller (see BottomUi.svelte), so the scroller is
 * physically bounded above it and can never render behind it. There is no
 * measurement and no reserved padding. These functions only decide *whether*
 * each piece is visible on a given route.
 *
 * Keeping them pure makes the visibility contract unit-testable.
 *
 * TRACES: UR-005 | DR-009
 */

export interface BottomUiVisibilityInput {
  /** Current route pathname, e.g. `$page.url.pathname`. */
  pathname: string;
  /** Whether the user is authenticated. */
  isAuthenticated: boolean;
}

/**
 * The bottom nav is shown on every authenticated route except the full-screen
 * player and the login route.
 */
export function showBottomNav({
  pathname,
  isAuthenticated,
}: BottomUiVisibilityInput): boolean {
  return (
    isAuthenticated &&
    !pathname.startsWith("/player/") &&
    !pathname.startsWith("/login")
  );
}

/**
 * The global (root-owned) mini player is shown on every route except the
 * full-screen player, login, and settings. Crucially this is NOT gated on
 * platform or on `/library` — the root owns the mini player everywhere, so the
 * library route must never render its own second one.
 */
export function showGlobalMiniPlayer({ pathname }: { pathname: string }): boolean {
  return (
    !pathname.startsWith("/player/") &&
    !pathname.startsWith("/login") &&
    !pathname.startsWith("/settings")
  );
}

/**
 * Routes that render their own full-height flex column (header + scroller +
 * their own in-flow BottomUi). The root leaves these as a plain clipped box and
 * does not render its own BottomUi. Every other route renders into the root's
 * scroller, with the root's in-flow BottomUi as a flex sibling below it.
 */
export function routeOwnsLayout({ pathname }: { pathname: string }): boolean {
  return (
    pathname.startsWith("/library") ||
    pathname.startsWith("/player/") ||
    pathname.startsWith("/login")
  );
}

/**
 * Whether the root layout should render the shared app header (logo, desktop
 * nav, and the account menu) for this route.
 *
 * Routes that own their layout (library) render their own AppHeader, so the
 * root must not double it up. `/settings` owns its content but deliberately has
 * no account menu (the user is already there). `/player/*` and `/login` are
 * immersive/chrome-free. Everything else authenticated (`/`, `/search`,
 * `/downloads`) gets the header from the root — the whole point of UR-054.
 *
 * TRACES: UR-054 | DR-076
 */
export function showGlobalHeader({
  pathname,
  isAuthenticated,
}: BottomUiVisibilityInput): boolean {
  return (
    isAuthenticated &&
    !routeOwnsLayout({ pathname }) &&
    !pathname.startsWith("/settings")
  );
}

/**
 * Whether any bottom UI is showing for this route (mini player, nav, or both).
 * The bottom UI is rendered in flex flow below the scroller (see BottomUi.svelte),
 * so this is purely a visibility question — there is no padding to reserve.
 */
export function showBottomUi(input: BottomUiVisibilityInput): boolean {
  return showBottomNav(input) || showGlobalMiniPlayer({ pathname: input.pathname });
}
