import clsx from "clsx";
import {
  Checkbox as CheckboxPrimitive,
  Label as LabelPrimitive,
} 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 CheckboxProps extends CheckboxPrimitive.CheckboxProps {
  "data-id": string;
  required?: boolean;
  size?: "xs" | "sm" | "md" | "lg";
  variant?: "solid" | "outline" | "subtle";
}

export const Checkbox = React.forwardRef(function Checkbox(
  args: CheckboxProps,
  ref,
) {
  const {
    defaultChecked,
    onChange,
    onFocus,
    onBlur,
    children,
    disabled,
    required,
    size = "md",
    variant = "solid",
    ...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 | "indeterminate";
    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 (
    <>
      <CheckboxPrimitive.Root
        ref={ref as any}
        className={clsx("__checkbox", className)}
        id={id}
        required={required}
        disabled={disabled}
        onCheckedChange={handleChange}
        checked={value}
        data-id={key}
        data-size={size}
        data-variant={variant}
        onClick={(e) => e.stopPropagation()}
        data-component="Checkbox$Brevity"
        {...props}
      >
        <CheckboxPrimitive.Indicator className={"__checkbox_indicator"}>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="3px"
            strokeLinecap="round"
            strokeLinejoin="round"
            className={styles.icon}
          >
            {value === "indeterminate" ? (
              <path d="M5 12h14" />
            ) : value ? (
              <polyline points="20 6 9 17 4 12" />
            ) : null}
          </svg>
        </CheckboxPrimitive.Indicator>
      </CheckboxPrimitive.Root>
      {children && (
        <LabelPrimitive.Root
          data-checkbox="label"
          data-disabled={disabled}
          className={clsx("__checkbox_label", styles.label)}
          htmlFor={id}
        >
          {children}
        </LabelPrimitive.Root>
      )}
    </>
  );
});
