import React from "react";
import { VariantProps, vcn } from "../shared";

const checkboxColors = {
  background: {
    default: "bg-neutral-200 dark:bg-neutral-700",
    hover: "hover:bg-neutral-300 dark:hover:bg-neutral-600",
    checked: "bg-neutral-300 dark:bg-neutral-400",
    checkedHover: "hover:bg-neutral-400 dark:hover:bg-neutral-300",
    disabled:
      'has-[input[type="checkbox"]:disabled]:bg-neutral-100 dark:has-[input[type="checkbox"]:disabled]:bg-neutral-800',
    disabledHover:
      "has-[input[type='checkbox']:disabled]:hover:bg-neutral-100 dark:has-[input[type='checkbox']:disabled]:hover:bg-neutral-800",
  },
  checkmark: "text-black dark:text-white",
};

const [checkboxVariant, resolveCheckboxVariantProps] = vcn({
  base: `inline-block rounded-md ${checkboxColors.checkmark} ${checkboxColors.background.disabled} ${checkboxColors.background.default} ${checkboxColors.background.hover} has-[input[type="checkbox"]:disabled]:cursor-not-allowed transition-colors duration-75 ease-in-out`,
  variants: {
    checked: {
      true: `${checkboxColors.background.checked} ${checkboxColors.background.checkedHover}`,
      false: ``,
    },
    size: {
      base: "size-[1em] p-0 [&>svg]:size-[1em]",
      md: "size-[1.5em] p-0.5 [&>svg]:size-[1.25em]",
      lg: "size-[1.75em] p-1 [&>svg]:size-[1.25em]",
    },
  },
  defaults: {
    checked: false,
    size: "md",
  },
});

interface CheckboxProps
  extends VariantProps<typeof checkboxVariant>,
    Omit<
      React.ComponentPropsWithoutRef<"input">,
      "type" | "className" | "size"
    > {}

const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
  (props, ref) => {
    const [variantProps, otherPropsCompressed] =
      resolveCheckboxVariantProps(props);
    const { defaultChecked, onChange, ...otherPropsExtracted } =
      otherPropsCompressed;

    // internally handles checked, so we can use checked value without prop
    const [checked, setChecked] = React.useState(defaultChecked ?? false);
    React.useEffect(() => {
      if (typeof variantProps.checked === "boolean") {
        setChecked(variantProps.checked);
      }
    }, [variantProps.checked]);

    const internalRef = React.useRef<HTMLInputElement | null>(null);

    return (
      <>
        <label className={checkboxVariant({ ...variantProps, checked })}>
          <input
            {...otherPropsExtracted}
            defaultChecked={defaultChecked}
            checked={
              typeof defaultChecked === "boolean"
                ? undefined
                : checked /* should be either uncontrolled (defaultChecked set) or controlled (checked set) */
            }
            onChange={(e) => {
              setChecked(e.currentTarget.checked);
              if (onChange) {
                onChange(e);
              }
            }}
            type="checkbox"
            className="hidden peer/checkbox"
            ref={(el) => {
              internalRef.current = el;
              if (typeof ref === "function") {
                ref(el);
              } else if (ref) {
                ref.current = el;
              }
            }}
          />
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="1em"
            height="1em"
            viewBox="0 0 24 24"
            className={`${checked ? "opacity-100" : "opacity-0"} transition-opacity duration-75 ease-in-out`}
          >
            <path
              fill="currentColor"
              d="M21 7L9 19l-5.5-5.5l1.41-1.41L9 16.17L19.59 5.59z"
            ></path>
          </svg>
        </label>
      </>
    );
  }
);

export { Checkbox };
