'use client';

import React from 'react';
import { cn } from '@/lib/utils';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { RiSearchLine, RiCloseLine } from '@remixicon/react';
import { Button } from '@/components/ui/button';

// A command palette in the shadcn shape, implemented on this project's own
// Dialog rather than cmdk so it stays dependency-free. Filtering is left to the
// caller, which suits async sources like the Storefront API.

function Command({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="command"
      className={cn(
        'flex h-full w-full flex-col overflow-hidden rounded-lg bg-popover text-popover-foreground',
        className
      )}
      {...props}
    />
  );
}

interface CommandDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  children: React.ReactNode;
  className?: string;
}

function CommandDialog({
  open,
  onOpenChange,
  children,
  className,
}: CommandDialogProps) {
  // Dialog portals straight into document.body, so hold off until mounted or
  // prerendering this component's page throws "document is not defined".
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => setMounted(true), []);

  if (!mounted) return null;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent
        showCloseButton={false}
        // DialogContent merges with clsx, so its own `p-6`/`gap-4` need the
        // important flag to lose to these.
        className={cn(
          'top-24 max-w-xl translate-y-0 overflow-hidden p-0! gap-0!',
          className
        )}
      >
        <Command>{children}</Command>
      </DialogContent>
    </Dialog>
  );
}

interface CommandInputProps
  extends Omit<React.ComponentProps<'input'>, 'onChange'> {
  onValueChange?: (value: string) => void;
  onClear?: () => void;
  onClose?: () => void;
}

function CommandInput({
  className,
  value,
  onValueChange,
  onClear,
  onClose,
  ...props
}: CommandInputProps) {
  const hasValue = Boolean(String(value ?? '').length);

  return (
    <div
      data-slot="command-input-wrapper"
      className="flex h-12 items-center gap-2 px-3"
    >
      <RiSearchLine size={18} className="shrink-0 text-muted-foreground" />
      <input
        data-slot="command-input"
        value={value}
        onChange={(event) => onValueChange?.(event.target.value)}
        className={cn(
          'flex h-10 w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',
          className
        )}
        {...props}
      />
      {hasValue && onClear && (
        <Button
          type="button"
          onClick={onClear}
          variant="ghost"
          size="sm"
          className="font-normal text-muted-foreground hover:text-foreground"
        >
          Clear
        </Button>
      )}
      {onClose && (
        <Button
          type="button"
          onClick={onClose}
          variant="ghost"
          size="icon-sm"
          aria-label="Close search"
        >
          <RiCloseLine size={18} />
        </Button>
      )}
    </div>
  );
}

function CommandList({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="command-list"
      className={cn('max-h-80 overflow-y-auto overflow-x-hidden', className)}
      {...props}
    />
  );
}

function CommandEmpty({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="command-empty"
      className={cn('px-4 py-8 text-center text-sm text-muted-foreground', className)}
      {...props}
    />
  );
}

interface CommandGroupProps extends React.ComponentProps<'div'> {
  heading?: string;
}

function CommandGroup({ className, heading, children, ...props }: CommandGroupProps) {
  return (
    <div
      data-slot="command-group"
      className={cn('px-2 py-2', className)}
      {...props}
    >
      {heading && (
        <div className="px-2 pb-2 text-xs uppercase tracking-wide text-muted-foreground">
          {heading}
        </div>
      )}
      {children}
    </div>
  );
}

function CommandItem({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="command-item"
      role="option"
      className={cn(
        'flex cursor-pointer select-none items-center gap-3 rounded-md px-2 py-2 text-sm outline-none hover:bg-accent',
        className
      )}
      {...props}
    />
  );
}

function CommandSeparator({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="command-separator"
      className={cn('h-px bg-border', className)}
      {...props}
    />
  );
}

export {
  Command,
  CommandDialog,
  CommandInput,
  CommandList,
  CommandEmpty,
  CommandGroup,
  CommandItem,
  CommandSeparator,
};
