import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import type React from 'react'
import { SvgTaillessLineArrowRight1 } from '@chainlink/blocks-icons'
import { getIconUrl } from '../../utils'
import { cn } from '../../utils/cn'
import { Tag } from '../Tag'
import type { TagProps } from '../Tag/Tag'
import { typographyVariants } from '../Typography'

/** Root state container for the dropdown. Manages open/closed state. Compose with DropdownMenuTrigger and DropdownMenuContent. */
const DropdownMenu = DropdownMenuPrimitive.Root
/** Element that opens the dropdown on click. Use `asChild` to make any element (e.g. a Button) the trigger. */
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
/** Groups related DropdownMenuItems under an optional DropdownMenuLabel. */
const DropdownMenuGroup = DropdownMenuPrimitive.Group
/** Portal that renders DropdownMenuContent outside the DOM tree. Used internally by DropdownMenuContent. */
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
/** Container for a nested submenu. Compose with DropdownMenuSubTrigger and DropdownMenuSubContent. */
const DropdownMenuSub = DropdownMenuPrimitive.Sub
/** Groups radio-style items where only one can be selected at a time. */
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup

DropdownMenuSub.displayName = 'DropdownMenuSub'

type DropdownMenuSubTriggerProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.SubTrigger
> & {
  /** When true, adds left padding to align with items that have an icon in the leading slot. */
  inset?: boolean
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>>
}

/** Item inside DropdownMenuSub that opens the nested submenu on hover or click. Shows a trailing arrow icon. */
const DropdownMenuSubTrigger = ({
  className,
  inset,
  children,
  ref,
  ...props
}: DropdownMenuSubTriggerProps) => (
  <DropdownMenuPrimitive.SubTrigger
    ref={ref}
    className={cn(
      'group flex cursor-default select-none items-center rounded-sm px-4 py-3 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
      inset && 'pl-8',
      className,
    )}
    {...props}
  >
    <>
      {children}
      <SvgTaillessLineArrowRight1
        color="currentColor"
        className="ml-auto h-3 w-3 text-muted-foreground transition-all duration-200 group-hover:h-4 group-hover:w-4 group-hover:text-foreground"
      />
    </>
  </DropdownMenuPrimitive.SubTrigger>
)
DropdownMenuSubTrigger.displayName =
  DropdownMenuPrimitive.SubTrigger.displayName

type DropdownMenuSubContentProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.SubContent
> & {
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.SubContent>>
}

const DropdownMenuSubContent = ({
  className,
  ref,
  ...props
}: DropdownMenuSubContentProps) => (
  <DropdownMenuPrimitive.Portal>
    <DropdownMenuPrimitive.SubContent
      ref={ref}
      className={cn(
        typographyVariants({ variant: 'body-s' }),
        'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded border border-solid border-border-active bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
        className,
      )}
      {...props}
    />
  </DropdownMenuPrimitive.Portal>
)
DropdownMenuSubContent.displayName =
  DropdownMenuPrimitive.SubContent.displayName

type DropdownMenuContentProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.Content
> & {
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Content>>
}

/**
 * Floating panel that contains the dropdown items. Renders inside a portal.
 * Accepts `side` and `align` props for positioning relative to the trigger.
 */
const DropdownMenuContent = ({
  className,
  children,
  sideOffset = 4,
  ref,
  ...props
}: DropdownMenuContentProps) => (
  <DropdownMenuPrimitive.Portal>
    <DropdownMenuPrimitive.Content
      ref={ref}
      sideOffset={sideOffset}
      className={cn(
        typographyVariants({ variant: 'body-s', color: 'foreground' }),
        'relative z-50 max-h-96 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded border border-solid border-border-active bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
        className,
      )}
      {...props}
    >
      {children}
    </DropdownMenuPrimitive.Content>
  </DropdownMenuPrimitive.Portal>
)
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName

type DropdownMenuItemProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.Item
> & {
  /** When true, adds left padding to align with items that have an icon in the leading slot. */
  inset?: boolean
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Item>>
}

/** A single clickable action in the dropdown. Use `disabled` to prevent interaction. */
const DropdownMenuItem = ({
  className,
  inset,
  ref,
  ...props
}: DropdownMenuItemProps) => (
  <DropdownMenuPrimitive.Item
    ref={ref}
    className={cn(
      'focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-4 py-3 text-sm outline-none transition-colors focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:text-muted-more-foreground',
      inset && 'pl-8',
      className,
    )}
    {...props}
  />
)
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName

type DropdownMenuCheckboxItemProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.CheckboxItem
> & {
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>>
}

/** A menu item with a checkbox indicator. Use `checked` and `onCheckedChange` to control its state. */
const DropdownMenuCheckboxItem = ({
  className,
  children,
  checked,
  ref,
  ...props
}: DropdownMenuCheckboxItemProps) => (
  <DropdownMenuPrimitive.CheckboxItem
    ref={ref}
    className={cn(
      'focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-3 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
      className,
    )}
    checked={checked}
    {...props}
  >
    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
      <DropdownMenuPrimitive.ItemIndicator>
        <img src={getIconUrl('blocks/check')} className="h-4 w-4" />
      </DropdownMenuPrimitive.ItemIndicator>
    </span>
    {children}
  </DropdownMenuPrimitive.CheckboxItem>
)
DropdownMenuCheckboxItem.displayName =
  DropdownMenuPrimitive.CheckboxItem.displayName

const Circle = (props: React.SVGProps<SVGSVGElement>) => (
  <svg viewBox="0 0 8 8" {...props}>
    <circle cx="4" cy="4" r="4" />
  </svg>
)

type DropdownMenuRadioItemProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.RadioItem
> & {
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>>
}

/** A menu item inside DropdownMenuRadioGroup. Only one radio item per group can be selected at a time. */
const DropdownMenuRadioItem = ({
  className,
  children,
  ref,
  ...props
}: DropdownMenuRadioItemProps) => (
  <DropdownMenuPrimitive.RadioItem
    ref={ref}
    className={cn(
      'focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-3 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
      className,
    )}
    {...props}
  >
    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
      <DropdownMenuPrimitive.ItemIndicator>
        <Circle className="h-2 w-2 fill-current" />
      </DropdownMenuPrimitive.ItemIndicator>
    </span>
    {children}
  </DropdownMenuPrimitive.RadioItem>
)
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName

type DropdownMenuLabelProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.Label
> & {
  /** When true, adds left padding to align with items that have an icon in the leading slot. */
  inset?: boolean
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Label>>
}

/** Non-interactive section label inside a DropdownMenuGroup. */
const DropdownMenuLabel = ({
  className,
  inset,
  ref,
  ...props
}: DropdownMenuLabelProps) => (
  <DropdownMenuPrimitive.Label
    ref={ref}
    className={cn(
      'px-4 py-3',
      typographyVariants({ variant: 'body-semi-s' }),
      inset && 'pl-8',
      className,
    )}
    {...props}
  />
)
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName

type DropdownMenuSeparatorProps = React.ComponentPropsWithoutRef<
  typeof DropdownMenuPrimitive.Separator
> & {
  ref?: React.Ref<React.ElementRef<typeof DropdownMenuPrimitive.Separator>>
}

/** Horizontal rule that visually separates groups of items. */
const DropdownMenuSeparator = ({
  className,
  ref,
  ...props
}: DropdownMenuSeparatorProps) => (
  <DropdownMenuPrimitive.Separator
    ref={ref}
    className={cn('-mx-1 my-1 h-px bg-border', className)}
    {...props}
  />
)
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName

/** Right-aligned keyboard shortcut hint rendered inside a DropdownMenuItem. */
const DropdownMenuShortcut = ({
  className,
  ...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
  return (
    <span
      className={cn(
        typographyVariants({ variant: 'body-s', color: 'muted-more' }),
        // keep right alignment but add left padding so the effective gap
        // between leading content and this shortcut matches gap-4
        'ml-auto pl-4 tracking-widest text-muted-more-foreground',
        className,
      )}
      {...props}
    />
  )
}
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'

/** Right-aligned Tag badge rendered inside a DropdownMenuItem. Useful for labels like "New" or "Beta". */
const DropdownMenuTag = ({
  className,
  size = 'sm',
  hideIcon = true,
  ...props
}: TagProps) => {
  return (
    <div className="ml-auto pl-4">
      <Tag size={size} hideIcon={hideIcon} className={className} {...props} />
    </div>
  )
}
DropdownMenuTag.displayName = 'DropdownMenuTag'

export {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTag,
  DropdownMenuTrigger,
}
