import * as React from 'react'
import * as SelectPrimitive from '@radix-ui/react-select'
import { Check, ChevronDown } from 'lucide-react'
import { cn } from '../lib/cn'

export interface SelectOption {
  value: string
  label: string
  disabled?: boolean
}

export interface SelectProps
  extends Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>, 'children'> {
  options: SelectOption[]
  placeholder?: string
  className?: string
  id?: string
  'aria-invalid'?: boolean
  'aria-describedby'?: string
  'aria-label'?: string
}

// Radix Select.Item rejects empty-string values — use a sentinel internally
const EMPTY = '__empty__'
const toRadix = (v: string) => (v === '' ? EMPTY : v)
const fromRadix = (v: string) => (v === EMPTY ? '' : v)

export const Select = React.forwardRef<
  React.ElementRef<typeof SelectPrimitive.Trigger>,
  SelectProps
>(({ options, placeholder, className, id, ...props }, ref) => {
  const { 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedby, 'aria-label': ariaLabel, onValueChange, value, ...rootProps } =
    props as SelectProps
  return (
    <SelectPrimitive.Root
      {...rootProps}
      value={value !== undefined ? toRadix(value) : undefined}
      onValueChange={onValueChange ? (v) => onValueChange(fromRadix(v)) : undefined}
    >
      <SelectPrimitive.Trigger
        ref={ref}
        id={id}
        aria-invalid={ariaInvalid}
        aria-describedby={ariaDescribedby}
        aria-label={ariaLabel}
        className={cn(
          'flex h-8 w-full items-center justify-between gap-2 rounded border bg-surface px-2 text-body-1 text-ink',
          ariaInvalid ? 'border-danger' : 'border-control-border',
          'focus:outline-none focus:ring-2 focus:ring-focus-ring',
          'disabled:opacity-50 disabled:pointer-events-none',
          className,
        )}
      >
        <SelectPrimitive.Value placeholder={placeholder} />
        <SelectPrimitive.Icon>
          <ChevronDown className="h-4 w-4 text-ink-faint" aria-hidden="true" />
        </SelectPrimitive.Icon>
      </SelectPrimitive.Trigger>
      <SelectPrimitive.Portal>
        <SelectPrimitive.Content
          position="popper"
          className="z-50 overflow-hidden rounded border border-control-border bg-surface text-ink shadow"
        >
          <SelectPrimitive.Viewport className="p-2">
            {options.map((opt) => (
              <SelectPrimitive.Item
                key={opt.value}
                value={toRadix(opt.value)}
                disabled={opt.disabled}
                className={cn(
                  'relative flex h-8 cursor-default select-none items-center rounded ps-8 pe-2 text-body-2 text-ink',
                  'data-[highlighted]:bg-hover data-[highlighted]:outline-none',
                  'data-[disabled]:opacity-50 data-[disabled]:pointer-events-none',
                )}
              >
                <span className="absolute inset-y-0 start-2 flex items-center">
                  <SelectPrimitive.ItemIndicator>
                    <Check className="h-4 w-4" aria-hidden="true" />
                  </SelectPrimitive.ItemIndicator>
                </span>
                <SelectPrimitive.ItemText>{opt.label}</SelectPrimitive.ItemText>
              </SelectPrimitive.Item>
            ))}
          </SelectPrimitive.Viewport>
        </SelectPrimitive.Content>
      </SelectPrimitive.Portal>
    </SelectPrimitive.Root>
  )
})
Select.displayName = 'Select'
