import clsx from "clsx";
import { Command as CommandPrimitive } from "cmdk";
import * as React from "react";
import { useGetKey, useGetSet } from "../../hooks";
import { useDebugEvents } from "../../utils";
import { composeEventHandlers } from "../../utils/composeEvents";
import * as styles from "./styles.module.css";

export const Command = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
  <CommandPrimitive
    ref={ref}
    className={clsx("__command", className)}
    data-component="Command$Brevity"
    {...props}
  />
)) as any;
Command.displayName = CommandPrimitive.displayName;

Command.CommandLoading = CommandPrimitive.Loading;

const INITIAL_STATE = { value: "" };
interface InputProps
  extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> {
  "data-id": string;
  onChange: (event: any) => void;
}
Command.CommandInput = React.forwardRef<
  React.ComponentRef<typeof CommandPrimitive.Input>,
  InputProps
>(({ onChange, ...rest }, ref) => {
  const key = useGetKey(rest);
  const [{ value }, setState] = useGetSet<{ value: string }>(
    key,
    INITIAL_STATE,
  );

  const {
    className,
    onChange: handleChange,
    ...props
  } = useDebugEvents<InputProps>(
    Object.assign(rest, {
      onChange: composeEventHandlers((value: string) => {
        setState({ value }, process.env.PREVIEW ? `onChange` : undefined);
      }, onChange),
    }),
  );
  return (
    <CommandPrimitive.Input
      ref={ref}
      className={clsx("__command-input", className)}
      value={value ?? ""}
      onValueChange={(value) => handleChange(value)}
      {...props}
    />
  );
});

Command.CommandInput.displayName = CommandPrimitive.Input.displayName;

Command.CommandList = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.List>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
  <CommandPrimitive.List
    ref={ref}
    className={clsx("__command-list", className)}
    {...props}
  />
));

Command.CommandList.displayName = CommandPrimitive.List.displayName;

Command.CommandEmpty = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Empty>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>(({ className, ...props }, ref) => (
  <CommandPrimitive.Empty
    ref={ref}
    className={clsx("__command-empty", className)}
    {...props}
  />
));
Command.CommandEmpty.displayName = CommandPrimitive.Empty.displayName;

Command.CommandGroup = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Group>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
  <CommandPrimitive.Group
    ref={ref}
    className={clsx("__command-group", styles.group, className)}
    {...props}
  />
));

Command.CommandGroup.displayName = CommandPrimitive.Group.displayName;

Command.CommandSeparator = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Separator>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
  <CommandPrimitive.Separator
    ref={ref}
    className={clsx("__command-separator", className)}
    {...props}
  />
));
Command.CommandSeparator.displayName = CommandPrimitive.Separator.displayName;

Command.CommandItem = React.forwardRef<
  React.ElementRef<typeof CommandPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
  <CommandPrimitive.Item
    ref={ref}
    className={clsx("__command-item", className)}
    {...props}
  />
));

Command.CommandItem.displayName = CommandPrimitive.Item.displayName;
