'use client';
import { FunctionComponent, useCallback, useMemo } from 'react';
import { Badge, Box, ButtonBase, Stack, Typography } from '@mui/material';
import { LinkToPage } from '@/utils';
import { AppIcon } from '@/components';
import { usePathname, useRouter } from '@/i18n/navigation';
import { matchActivePath } from '../matchActivePath';

interface Props {
  items: Array<LinkToPage>;
}

const ICON_SIZE = 22;
/** The active pill behind the icon — wide enough to read as a target, short enough to stay a pill. */
const PILL_WIDTH = 52;
const PILL_HEIGHT = 28;

/**
 * The app's only navigation surface: a bottom tab bar carrying one destination per top-level
 * area. It replaced the drawer + hamburger outright — on a phone-width frame a drawer hides the
 * whole information architecture behind a tap and gives the top bar a job it doesn't need.
 *
 * Each tab is a `ButtonBase` (not MUI's `BottomNavigation`) so the active state can be a pill
 * that fills in behind the icon rather than a color-only swap: the shape change is what makes
 * the selection legible at a glance. The transition reads through `--bal-motion-fast`, so the
 * app-wide reduced-motion gate (globals.css) already collapses it — no local branch.
 *
 * Locale-aware via the `@/i18n/navigation` wrapper (no manual `/${locale}` prefixing), with the
 * shared `matchActivePath` longest-prefix helper deciding the active tab, so a nested route
 * (`/patients/123`) still lights up its parent.
 * @component BottomBar
 */
const BottomBar: FunctionComponent<Props> = ({ items }) => {
  const router = useRouter();
  const pathname = usePathname();

  // A tab can claim paths outside its own subtree (`matchPaths`), so the longest-prefix match runs
  // over every claimed path and the winner is mapped back to the tab that claimed it.
  const activePath = useMemo(() => {
    const claims = items.flatMap((item) =>
      !item.path ? [] : [item.path, ...(item.matchPaths ?? [])].map((claimed) => ({ claimed, tab: item.path as string }))
    );
    const winner = matchActivePath(pathname, claims.map((claim) => claim.claimed));
    return claims.find((claim) => claim.claimed === winner)?.tab;
  }, [items, pathname]);

  const onSelect = useCallback(
    (item: LinkToPage) => {
      if (item.onSelect) {
        item.onSelect();
        return;
      }
      if (item.path) router.push(item.path);
    },
    [router]
  );

  return (
    // The bar floats: it is inset from the frame edges and fully rounded, so the page background
    // runs behind and around it instead of the bar sealing off the bottom of the screen with an
    // edge-to-edge slab. It is still a flex sibling of the scrolling <main> (AppFrame), not an
    // overlay — content is never hidden underneath it and no screen needs bottom padding for it.
    <Box
      component="nav"
      sx={{
        px: 1.5,
        pt: 0.5,
        paddingBottom: 'calc(env(safe-area-inset-bottom) + 10px)',
      }}
    >
      <Stack
        direction="row"
        sx={{
          px: 0.75,
          py: 1,
          gap: 0.25,
          bgcolor: 'background.paper',
          border: '1px solid',
          borderColor: 'divider',
          borderRadius: 'var(--bal-radius-pill)',
          boxShadow: 'var(--bal-shadow-2)',
        }}
      >
        {items.map((item) => {
          const isActive = Boolean(item.path) && item.path === activePath;
          return (
            <ButtonBase
              key={`${item.title}-${item.path}`}
              onClick={() => onSelect(item)}
              aria-current={isActive ? 'page' : undefined}
              sx={{
                flex: 1,
                minWidth: 0,
                flexDirection: 'column',
                gap: 0.25,
                py: 0.25,
                // Matches the bar's own shape so the ripple/focus ring never squares off a
                // corner against the rounded container behind it.
                borderRadius: 'var(--bal-radius-pill)',
              }}
            >
              <Badge
                badgeContent={item.badgeCount ?? 0}
                max={99}
                invisible={!item.badgeCount}
                sx={{ '& .MuiBadge-badge': { bgcolor: 'var(--bal-error)', color: 'var(--bal-error-contrast)' } }}
              >
                <Box
                  sx={{
                    width: PILL_WIDTH,
                    height: PILL_HEIGHT,
                    display: 'grid',
                    placeItems: 'center',
                    borderRadius: 'var(--bal-radius-pill)',
                    bgcolor: isActive ? 'var(--bal-primary-soft)' : 'transparent',
                    transition: 'background-color var(--bal-motion-fast) var(--bal-easing-standard)',
                  }}
                >
                  <AppIcon
                    icon={item.icon}
                    size={ICON_SIZE}
                    color={isActive ? 'var(--bal-primary)' : 'var(--bal-text-secondary)'}
                    strokeWidth={isActive ? 2.1 : 1.75}
                  />
                </Box>
              </Badge>
              <Typography
                variant="caption"
                noWrap
                sx={{
                  maxWidth: '100%',
                  fontWeight: isActive ? 700 : 400,
                  color: isActive ? 'var(--bal-primary)' : 'text.secondary',
                }}
              >
                {item.title}
              </Typography>
            </ButtonBase>
          );
        })}
      </Stack>
    </Box>
  );
};

export default BottomBar;
