import clsx from 'clsx';
import React, { useRef, useState } from 'react';
import {
  ConfirmDialog,
  ConfirmationConfig,
  ConfirmationMode,
} from '../../ConfirmDialog';
import { BaseFormControl, BaseInputEvents } from '../Form.models';
import { FormElementContainer } from '../FormElementContainer';
import classes from './Checkbox.scss';

export interface CheckboxProps
  extends BaseFormControl,
    Omit<BaseInputEvents, 'onChange'> {
  /** Current value the form control has */
  value?: boolean;
  /** Whether or not the control should start focused (default: false) */
  autoFocus?: boolean;
  /** If set to 'Advanced', action will require confirmation via a confirmation pop up. (default: 'None') */
  confirmationMode?: Extract<ConfirmationMode, 'None' | 'Advanced'>;
  /** Optional text overrides for the confirmation pop up. */
  confirmationConfig?: ConfirmationConfig;
  onChange?: (value: boolean) => void;
}

export const Checkbox: React.FC<CheckboxProps> = ({
  name,
  id,
  value = false,
  disabled = false,
  error,
  autoFocus = false,
  confirmationMode = 'None',
  confirmationConfig = {},
  onChange,
  onBlur,
  onFocus,
  className = '',
  ...rest
}) => {
  const errorMsg: string | undefined = error;

  const [confirmation, setConfirmation] = useState<boolean>(false);
  const [referenceElement, setReferenceElement] = useState<HTMLElement>();
  const ref = useRef<boolean>();

  const { title, body, cancelButtonText, confirmButtonText, onConfirmOpen } =
    confirmationConfig;

  const onCancelHandler = (): void => {
    ref.current = undefined;
    setConfirmation(false);
  };

  const onConfirmHandler = (): void => {
    onChange && onChange(ref.current as boolean);

    ref.current = undefined;
    setConfirmation(false);
  };

  return (
    <FormElementContainer
      {...rest}
      className={clsx(classes.container, 'checkbox-container', className)}
      error={errorMsg}
      dataTestFieldType="Checkbox"
      htmlFor={id ?? name}
    >
      <input
        id={id ?? name}
        name={name}
        ref={setReferenceElement as React.LegacyRef<HTMLInputElement>}
        type="checkbox"
        className={clsx({
          [classes.hasConfirm]: confirmation,
          [classes.hasError]: errorMsg !== undefined,
        })}
        checked={value}
        // Open issue https://github.com/facebook/react/issues/6321
        // "checked" does not update so we need another attribute:
        data-test-checked={value}
        disabled={disabled}
        autoFocus={autoFocus}
        onChange={(e) => {
          if (confirmationMode === 'Advanced') {
            ref.current = e.currentTarget.checked;
            setConfirmation(true);
            return;
          }

          onChange && onChange(e.currentTarget.checked);
        }}
        onBlur={onBlur}
        onFocus={onFocus}
      />
      {confirmation && (
        <ConfirmDialog
          className={clsx(classes.confirmDialog)}
          referenceElement={referenceElement}
          title={title}
          cancelButtonText={cancelButtonText}
          confirmButtonText={confirmButtonText}
          onCancel={onCancelHandler}
          onConfirm={onConfirmHandler}
          onConfirmOpen={onConfirmOpen}
        >
          {body}
        </ConfirmDialog>
      )}
    </FormElementContainer>
  );
};
