import React, { useCallback, useMemo } from "react";
import { Controller, RegisterOptions, useFormContext } from "react-hook-form";
import { getCheckedClassName } from "../../../util/stringUtil";

export type RadioButtonProps = {
  value: string;
  label: string | React.JSX.Element;
  subLabel?: string;
  name: string;
  id: string;
  labelClassName?: string;
  cardClassName?: string;
  icon?: React.JSX.Element;
  type: RadioType;
  disabled?: boolean;
  registerOptions?: RegisterOptions;
  children?: React.ReactNode;
  defaultBGColor?: string;
};

export type RadioType = "card" | "default";

export default function RadioButton({
  value,
  label,
  subLabel,
  name,
  id,
  labelClassName,
  cardClassName,
  children,
  disabled = false,
  registerOptions,
  defaultBGColor,
  icon,
  type,
}: RadioButtonProps): React.JSX.Element {
  const [active, setActive] = React.useState(false);

  const bgColor = defaultBGColor ? defaultBGColor : "bg-white";

  const defaultClassName = "border-akzent-zwei";
  const selectedClassName =
    "border-interactive-primary-default bg-brand-primary-10";

  const wrapperBaseClassName = "rounded-lg border cursor-pointer";
  const baseClassName = `${wrapperBaseClassName} ${type === "card" ? "form-check form-check-inline" : "text-center py-2"} `;

  const { control, setValue, trigger, watch } = useFormContext(); // retrieve all hook methods
  const watchCurrentValue = watch(name);

  React.useEffect(() => {
    setActive(watchCurrentValue === value);
  }, [watchCurrentValue, value]);

  const registerReturn = useMemo(
    () => (!disabled ? registerOptions : undefined),
    [disabled]
  );

  const renderedRadioButton = useCallback(
    ({ field: { onChange } }) => {
      return (
        <input
          className={`hover:border-interactive-primary-hover active:border-interactive-primary-pressed
  form-check-input rounded-full h-4 w-4 border-2 border-interactive-primary-default ${bgColor} transition duration-200 mb-1 align-top cursor-pointer
  focus-visible:ring-4 focus-visible:ring-interactive-primary-focus focus-visible:ring-offset-0
  checked:ring-inset checked:ring-white checked:bg-none checked:ring-0 checked:!ring-offset-2 peer
  disabled:border-neutral-medium-light disabled:cursor-default disabled:checked:bg-neutral-medium-light disabled:${bgColor} hover:disabled:${bgColor} hover:disabled:border-neutral-medium-light
  `}
          type="radio"
          name={name}
          id={id}
          value={value}
          disabled={disabled}
          checked={active}
          onChange={onChange}
        />
      );
    },
    [name, disabled, value, id, active]
  );

  return (
    <div
      className={`${
        !disabled
          ? getCheckedClassName(
              active,
              baseClassName,
              selectedClassName,
              defaultClassName
            )
          : "border border-neutral-medium-light rounded-lg cursor-default py-2"
      }
      } ${cardClassName}`}
      onClick={async () => {
        if (!disabled) {
          setValue(name, value, { shouldDirty: true });
          await trigger(name);
        }
      }}
    >
      <Controller
        render={renderedRadioButton}
        name={name}
        control={control}
        rules={registerReturn}
      />

      <label
        className={`text-neutral-very-dark w-11/12 truncate cursor-pointer peer-disabled:cursor-default peer-disabled:text-neutral-medium-light ${labelClassName}`}
        htmlFor={id}
      >
        <div>{label}</div>
        {subLabel && <b>{subLabel}</b>}
      </label>
      <div
        className="
      fill-brand-primary"
      >
        {icon}
      </div>
      {active && children}
    </div>
  );
}
