import * as React from 'react';
import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
import { cva } from 'class-variance-authority';
import { ChevronDown } from 'lucide-react';

import { cn } from '@/lib/utils';

/**
 * Tailwind 3.4 port of shadcn's navigation-menu.
 *
 * The registry version on ui.shadcn.com now targets Tailwind 4 and leans on
 * v4-only pieces (`size-*` everywhere, `@theme` tokens, the CSS-first config).
 * Everything below is expressible in 3.4 with tailwindcss-animate, which is
 * already a plugin here. Three things break if you change them carelessly:
 *
 * 1. VIEWPORT POSITIONING. The viewport is not inside the trigger — Radix
 *    hoists every open panel into one shared box. It only lands under the menu
 *    because it sits in an `absolute left-0 top-full` wrapper that is a child
 *    of the *Root*, and because the Root is `relative`. Move the wrapper out of
 *    the Root, or drop `relative`, and the panel positions against the page.
 * 2. WIDTH. `--radix-navigation-menu-viewport-width` is the measured width of
 *    the open panel. Without that binding the viewport shrink-wraps to nothing
 *    on the first frame and the panel visibly snaps to size.
 * 3. Z-INDEX. The header that hosts this is `position: sticky` with a
 *    `backdrop-filter`, which makes it a stacking context, so the viewport's
 *    z-index competes only inside the header — but it must still clear the
 *    header's own translucent background, hence z-50 rather than the z-10 the
 *    upstream recipe uses.
 */
function NavigationMenu({
  className,
  children,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root>) {
  return (
    <NavigationMenuPrimitive.Root
      className={cn('relative z-50 flex max-w-max flex-1 items-center justify-center', className)}
      {...props}
    >
      {children}
      <NavigationMenuViewport />
    </NavigationMenuPrimitive.Root>
  );
}

function NavigationMenuList({
  className,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
  return (
    <NavigationMenuPrimitive.List
      className={cn('group flex flex-1 list-none items-center justify-center gap-1', className)}
      {...props}
    />
  );
}

const NavigationMenuItem = NavigationMenuPrimitive.Item;

const navigationMenuTriggerStyle = cva(
  'group inline-flex h-9 w-max items-center justify-center gap-1 rounded-md px-3 py-2 text-sm font-medium text-fg transition-colors duration-1 ease-enter hover:bg-surface-2 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:bg-surface-2',
);

function NavigationMenuTrigger({
  className,
  children,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
  return (
    <NavigationMenuPrimitive.Trigger
      className={cn(navigationMenuTriggerStyle(), className)}
      {...props}
    >
      {children}
      <ChevronDown
        aria-hidden="true"
        className="relative top-px size-3.5 text-muted transition-transform duration-3 ease-enter group-data-[state=open]:rotate-180"
      />
    </NavigationMenuPrimitive.Trigger>
  );
}

/**
 * `data-motion` is set by Radix when you move sideways from one open panel to
 * the next; the slide utilities below are what make that read as one surface
 * sliding rather than two panels blinking. The `md:absolute` flip is the
 * upstream trick that lets the content measure itself at full width before the
 * viewport adopts that width.
 */
function NavigationMenuContent({
  className,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
  return (
    <NavigationMenuPrimitive.Content
      className={cn(
        'left-0 top-0 w-full duration-3 ease-enter data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto',
        className,
      )}
      {...props}
    />
  );
}

const NavigationMenuLink = NavigationMenuPrimitive.Link;

function NavigationMenuViewport({
  className,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
  return (
    <div className="absolute left-0 top-full z-50 flex justify-center">
      <NavigationMenuPrimitive.Viewport
        className={cn(
          'relative mt-2 h-[var(--radix-navigation-menu-viewport-height)] w-full origin-top overflow-hidden rounded-xl border border-border bg-surface text-fg shadow-xl',
          'transition-[width,height] duration-3 ease-enter',
          'data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
          'md:w-[var(--radix-navigation-menu-viewport-width)]',
          className,
        )}
        {...props}
      />
    </div>
  );
}

function NavigationMenuIndicator({
  className,
  ...props
}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
  return (
    <NavigationMenuPrimitive.Indicator
      className={cn(
        'top-full z-50 flex h-2 items-end justify-center overflow-hidden duration-3 ease-enter data-[state=hidden]:animate-out data-[state=visible]:animate-in data-[state=hidden]:fade-out data-[state=visible]:fade-in',
        className,
      )}
      {...props}
    >
      {/* Rotated square, half-clipped by the parent's overflow — a caret that
          inherits the panel's border and surface without a second SVG. */}
      <div className="relative top-[60%] size-2 rotate-45 rounded-tl-sm border-l border-t border-border bg-surface" />
    </NavigationMenuPrimitive.Indicator>
  );
}

export {
  NavigationMenu,
  NavigationMenuList,
  NavigationMenuItem,
  NavigationMenuContent,
  NavigationMenuTrigger,
  NavigationMenuLink,
  NavigationMenuIndicator,
  NavigationMenuViewport,
  navigationMenuTriggerStyle,
};
