import clsx from "clsx";
import { Label as LabelPrimitive, Switch as SwitchPrimitive } from "radix-ui";
import * as React from "react";
import { useGetSet } from "../../hooks";
import { useGetKey } from "../../hooks/useGetKey";
import { useDebugEvents } from "../../utils";
import { composeEventHandlers } from "../../utils/composeEvents";
import * as styles from "./styles.module.css";

export interface SwitchProps extends React.ComponentPropsWithoutRef<"button"> {
  "data-id": string;
  required?: boolean;
}

export const Switch = React.forwardRef(function Switch(args: SwitchProps, ref) {
  const {
    defaultChecked,
    onChange,
    onFocus,
    onBlur,
    children,
    disabled,
    required,
    ...rest
  } = args;
  const id = React.useId();
  const key = useGetKey(rest);
  const inputRef = React.useRef<HTMLInputElement>(null);
  const initialValue = React.useMemo(
    () => ({ value: defaultChecked }),
    [defaultChecked],
  );
  const [{ value }, setState] = useGetSet<{
    value?: boolean;
    focused?: boolean;
  }>(key, initialValue);
  const {
    className,
    onChange: handleChange,
    ...props
  } = useDebugEvents<any>(
    Object.assign(rest, {
      onFocus: composeEventHandlers(
        (event: React.ChangeEvent<HTMLInputElement>) => {
          setState({ focused: true });
        },
        onFocus,
      ),
      onChange: composeEventHandlers((value: boolean) => {
        setState({ value });
      }, onChange),
      onBlur: composeEventHandlers(
        (event: React.ChangeEvent<HTMLInputElement>) => {
          setState({ focused: false });
        },
        onBlur,
      ),
    }),
  );

  React.useEffect(() => {
    const parentForm = inputRef.current?.form;
    const handler = () => {
      setState({ value: !!defaultChecked });
    };
    parentForm?.addEventListener("reset", handler);
    return () => {
      parentForm?.removeEventListener("reset", handler);
    };
  }, []);

  return (
    <div
      className={clsx("__switch-container", styles.container, className)}
      data-component="Switch$Brevity"
      {...props}
      data-id={key}
    >
      <SwitchPrimitive.Root
        ref={ref as any}
        className={clsx("__switch-root", styles.root)}
        id={id}
        required={required}
        disabled={disabled}
        onCheckedChange={handleChange}
        checked={value}
      >
        <SwitchPrimitive.Thumb
          className={clsx("__switch-thumb", styles.thumb)}
        />
      </SwitchPrimitive.Root>
      {children && (
        <LabelPrimitive.Root
          data-disabled={disabled}
          className={clsx("__switch-label", styles.label)}
          htmlFor={id}
        >
          {children}
        </LabelPrimitive.Root>
      )}
    </div>
  );
});
