import * as React from 'react'
import { DialogProps } from '@radix-ui/react-dialog'
import { Command as CommandPrimitive } from 'cmdk'
import { Search } from 'lucide-react'
import tw from 'twin.macro'
import * as DialogPrimitive from '../dialog/dialog'

const Command = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>((props, ref) => (
  <CommandPrimitive
    ref={ref}
    tw="flex h-full w-full flex-col overflow-hidden rounded-lg bg-white dark:bg-slate-800"
    {...props}
  />
))
Command.displayName = CommandPrimitive.displayName

type CommandDialogProps = DialogProps

function CommandDialog({ children, ...props }: CommandDialogProps) {
  return (
    <DialogPrimitive.Root {...props}>
      <DialogPrimitive.Content tw="overflow-hidden p-0 shadow-2xl [&_[dialog-overlay]]:bg-red-100">
        <Command
          css={tw`
          [&_[cmdk-group]]:px-2
          [&_[cmdk-group-heading]]:px-2
          [&_[cmdk-group-heading]]:font-medium
          [&_[cmdk-group-heading]]:text-slate-500
          [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3
          [&_[cmdk-input]]:h-12
          [&_[cmdk-item]_svg]:h-5
          [&_[cmdk-item]_svg]:w-5
          [&_[cmdk-input-wrapper]_svg]:h-5
          [&_[cmdk-input-wrapper]_svg]:w-5
          [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0
        `}
        >
          {children}
        </Command>
      </DialogPrimitive.Content>
    </DialogPrimitive.Root>
  )
}

const CommandInput = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Input>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>((props, ref) => (
  <div
    tw="flex items-center border-b border-b-slate-100 px-4 dark:border-b-slate-700"
    cmdk-input-wrapper=""
  >
    <Search tw="mr-2 h-4 w-4 shrink-0 opacity-50" />
    <CommandPrimitive.Input
      ref={ref}
      css={tw`
        flex
        h-11
        w-full
        rounded-md
        bg-transparent
        py-3
        text-sm
        outline-none
        placeholder:text-slate-400
        disabled:cursor-not-allowed
        disabled:opacity-50
        dark:text-slate-50
      `}
      {...props}
    />
  </div>
))

CommandInput.displayName = CommandPrimitive.Input.displayName

const CommandList = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.List>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>((props, ref) => (
  <CommandPrimitive.List
    ref={ref}
    tw="max-h-[300px] overflow-y-auto overflow-x-hidden"
    {...props}
  />
))

CommandList.displayName = CommandPrimitive.List.displayName

const CommandEmpty = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Empty>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
  <CommandPrimitive.Empty ref={ref} tw="py-6 text-center text-sm" {...props} />
))

CommandEmpty.displayName = CommandPrimitive.Empty.displayName

const CommandGroup = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Group>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>((props, ref) => (
  <CommandPrimitive.Group
    ref={ref}
    css={tw`
      overflow-hidden
      py-3
      px-2
      text-slate-700
      dark:text-slate-400
      [&_[cmdk-group-heading]]:px-2
      [&_[cmdk-group-heading]]:pb-1.5
      [&_[cmdk-group-heading]]:text-sm
      [&_[cmdk-group-heading]]:font-semibold
      [&_[cmdk-group-heading]]:text-slate-900
      [&_[cmdk-group-heading]]:dark:text-slate-300
    `}
    {...props}
  />
))

CommandGroup.displayName = CommandPrimitive.Group.displayName

const CommandSeparator = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Separator>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>((props, ref) => (
  <CommandPrimitive.Separator
    ref={ref}
    tw="-mx-1 h-px bg-slate-100 dark:bg-slate-700"
    {...props}
  />
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName

const CommandItem = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>((props, ref) => (
  <CommandPrimitive.Item
    ref={ref}
    css={tw`
      relative
      flex
      cursor-default
      select-none
      items-center
      rounded-md
      py-1.5
      px-2
      text-sm
      font-medium
      outline-none
      // aria-selected:bg-slate-100
      data-[disabled]:pointer-events-none
      data-[disabled]:opacity-50
      // dark:aria-selected:bg-slate-700
    `}
    {...props}
  />
))

CommandItem.displayName = CommandPrimitive.Item.displayName

function CommandShortcut(props: React.HTMLAttributes<HTMLSpanElement>) {
  return <span tw="ml-auto text-xs tracking-widest text-slate-500" {...props} />
}
CommandShortcut.displayName = 'CommandShortcut'

const _Command = Command
export {
  _Command as Root,
  CommandDialog as Dialog,
  CommandInput as Input,
  CommandList as List,
  CommandEmpty as Empty,
  CommandGroup as Group,
  CommandItem as Item,
  CommandShortcut as Shortcut,
  CommandSeparator as Separator,
}
