import { Badge, Group, Menu, UnstyledButton, rem } from '@mantine/core';
import { forwardRef } from 'react';
import { IconChevronDown } from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
import type { NavItem } from './AppSidebar';
import {
  badgeLabel,
  isBranchActive,
  isItemActive,
  toSections,
  type NavEntries,
} from './nav-utils';

interface AppTopNavProps {
  navItems: NavEntries;
  activePath: string;
  onNavigate: (item: NavItem) => void;
}

/**
 * Horizontal navigation for the top-bar layout.
 *
 * Every destination used to render as a sibling button in one horizontally
 * scrolling strip, so with twenty-odd of them most were off-screen and the
 * grouping that the sidebar already had was thrown away. Here each section
 * collapses to a single labelled dropdown, which fits and keeps the same
 * information architecture as the sidebar. Sections that still do not fit
 * scroll horizontally rather than dropping off the edge — under ~1100px the
 * last one or two were simply unreachable.
 */
export function AppTopNav({ navItems, activePath, onNavigate }: AppTopNavProps) {
  const { t } = useTranslation();
  const sections = toSections(navItems);

  return (
    <Group
      gap={rem(2)}
      h="100%"
      wrap="nowrap"
      role="navigation"
      aria-label={t('nav.primary', 'Primary')}
      style={{ flex: 1, minWidth: 0, overflowX: 'auto', scrollbarWidth: 'none' }}
    >
      {sections.map((section, index) => {
        // An unlabelled leading block (Dashboard) is a plain link, not a menu.
        if (!section.label) {
          return section.items.map((item) => (
            <TopNavButton
              key={item.label}
              label={t(item.label)}
              active={isBranchActive(item, activePath)}
              badge={badgeLabel(item.badge)}
              soon={item.soon}
              onClick={() => onNavigate(item)}
            />
          ));
        }

        const sectionActive = section.items.some((item) =>
          isBranchActive(item, activePath),
        );
        const pending = section.items.reduce((sum, item) => {
          const own = typeof item.badge === 'number' ? item.badge : 0;
          const nested = (item.children ?? []).reduce(
            (n, child) => n + (typeof child.badge === 'number' ? child.badge : 0),
            0,
          );
          return sum + own + nested;
        }, 0);

        return (
          <Menu
            key={section.label ?? `section-${index}`}
            trigger="click-hover"
            openDelay={80}
            closeDelay={140}
            position="bottom-start"
            withinPortal
            shadow="md"
          >
            <Menu.Target>
              <TopNavButton
                label={t(section.label)}
                active={sectionActive}
                badge={badgeLabel(pending)}
                withChevron
              />
            </Menu.Target>
            <Menu.Dropdown>
              {section.items.map((item) =>
                item.children?.length ? (
                  <Menu.Sub key={item.label} position="right-start">
                    <Menu.Sub.Target>
                      <Menu.Sub.Item leftSection={<item.icon size={16} stroke={1.6} />}>
                        {t(item.label)}
                      </Menu.Sub.Item>
                    </Menu.Sub.Target>
                    <Menu.Sub.Dropdown>
                      {item.children.map((child) => (
                        <Menu.Item
                          key={child.label}
                          leftSection={<child.icon size={16} stroke={1.6} />}
                          onClick={() => onNavigate(child)}
                          disabled={child.soon}
                        >
                          {t(child.label)}
                        </Menu.Item>
                      ))}
                    </Menu.Sub.Dropdown>
                  </Menu.Sub>
                ) : (
                  <Menu.Item
                    key={item.label}
                    leftSection={<item.icon size={16} stroke={1.6} />}
                    rightSection={
                      item.soon ? (
                        <Badge size="xs" variant="light" color="gray" radius="sm">
                          {t('nav.soon', 'Soon')}
                        </Badge>
                      ) : (
                        badgeLabel(item.badge) !== null && (
                          <Badge size="xs" variant="filled" color="red" radius="sm">
                            {badgeLabel(item.badge)}
                          </Badge>
                        )
                      ) || undefined
                    }
                    onClick={() => onNavigate(item)}
                    // `soon` screens have no backend; the Menu.Item's own
                    // disabled styling plus the badge explains why.
                    disabled={item.soon}
                    aria-current={isItemActive(item, activePath) ? 'page' : undefined}
                  >
                    {t(item.label)}
                  </Menu.Item>
                ),
              )}
            </Menu.Dropdown>
          </Menu>
        );
      })}
    </Group>
  );
}

interface TopNavButtonProps {
  label: string;
  active: boolean;
  badge?: string | null;
  soon?: boolean;
  withChevron?: boolean;
  onClick?: () => void;
}

/**
 * `Menu.Target` positions its dropdown against the ref it passes to its child,
 * so a plain function component here left every section menu anchored at the
 * top-left of the viewport, covering the header instead of opening under the
 * button that was clicked. The rest props carry Menu's own click and aria
 * handling onto the real button.
 */
const TopNavButton = forwardRef<HTMLButtonElement, TopNavButtonProps>(
  function TopNavButton(
    { label, active, badge, soon, withChevron, onClick, ...others },
    ref,
  ) {
    return (
      <UnstyledButton
        ref={ref}
        onClick={onClick}
        {...others}
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: rem(6),
          padding: `0 ${rem(14)}`,
          height: '100%',
          flexShrink: 0,
          borderBottom: '2px solid',
          borderBottomColor: active
            ? 'var(--mantine-color-blue-6)'
            : 'transparent',
          color: active
            ? 'var(--mantine-color-blue-6)'
            : 'var(--mantine-color-gray-6)',
          fontWeight: active ? 600 : 500,
          fontSize: rem(14),
          whiteSpace: 'nowrap',
          opacity: soon ? 0.55 : 1,
          marginBottom: -1,
        }}
      >
        <span>{label}</span>
        {badge !== null && badge !== undefined && (
          <Badge size="xs" variant="filled" color="red" radius="sm">
            {badge}
          </Badge>
        )}
        {withChevron && <IconChevronDown size={14} stroke={2} />}
      </UnstyledButton>
    );
  },
);
