/**
 * @file AuthForm.tsx - Authentication form used on both the login page and the reauthentication modal.
 * Provides username, password, and optional domain fields with Bootstrap validation.
 * When rendered inside a modal (via modalProps), the username field is pre-filled and disabled, and a cancel button is shown alongside the login button.
 */

import {
  type Dispatch,
  type FC,
  type FormEvent,
  type ReactNode,
  type SetStateAction,
  useRef,
  useState,
} from 'react';
import { FloatingLabel, Form, Modal } from 'react-bootstrap';
import { useAuth } from '../contexts/AuthContext.tsx';
import { useTranslation } from 'react-i18next';

/** Props for the login button rendered by the parent. */
interface LoginButtonProps {
  /** The rendered button element */
  element: ReactNode;

  /** Callback to show/hide a loading spinner while the login request is in flight */
  setShowLoadingSpinner: Dispatch<SetStateAction<boolean>>;
}

/** Props for the optional cancel button (only used in modal mode). */
interface CancelButtonProps {
  /** The rendered button element */
  element: ReactNode;
}

/** Props for the AuthForm component. */
interface AuthFormProps {
  /** Callback invoked after a successful login (e.g., navigate or close modal) */
  loginThen: () => void;

  /** Login button (always required) and an optional cancel button for modal usage */
  buttons:
    | {
        login: LoginButtonProps;
      }
    | {
        login: LoginButtonProps;
        cancel: CancelButtonProps;
      };

  /** When provided, the form renders inside Modal.Body/Modal.Footer layout with a subtitle and the username field locked to the current user */
  modalProps?: { subtitle: string };
}

/**
 * Authentication form component for use with the login page and the reauthentication modal.
 * Renders username, password, and optional domain fields wrapped in a Bootstrap validated form.
 * Adapts its layout depending on whether it is rendered standalone (login page) or inside a modal (reauthentication flow).
 */
export const AuthForm: FC<AuthFormProps> = ({
  loginThen,
  buttons,
  modalProps,
}) => {
  const { username, login } = useAuth();

  // Bootstrap native form validation
  const [validated, setValidated] = useState(false);
  // Controls whether to show the "domain is optional" feedback message
  const [showEmptyDomainFeedback, setShowEmptyDomainFeedback] = useState(true);
  // Form input refs
  const usernameInput = useRef<HTMLInputElement>(null);
  const passwordInput = useRef<HTMLInputElement>(null);
  const domainInput = useRef<HTMLInputElement>(null);

  /**
   * Fires when the form is submitted (log in button is clicked).
   *
   * @param event HTML form event
   */
  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    event.stopPropagation();

    const form = event.currentTarget;
    // Validate form and attempt login
    if (form.checkValidity()) {
      buttons.login.setShowLoadingSpinner(true);

      login({
        userName: usernameInput.current?.value as string,
        password: passwordInput.current?.value as string,
        domain: domainInput.current?.value as string,
      })
        .then(loginThen)
        .catch(() => {
          buttons.login.setShowLoadingSpinner(false);
        });
    } else {
      setValidated(true);
      buttons.login.setShowLoadingSpinner(false);
    }
  };

  // Determine if the form should render in modal mode (requires both modalProps and a cancel button)
  const isModal = modalProps !== undefined && 'cancel' in buttons;

  const { t } = useTranslation(undefined, {
    keyPrefix: 'components.auth_form',
  });

  // Reusable input controls element
  const InputControls = (
    <>
      <FloatingLabel
        controlId={'username-input'}
        label={
          <span>
            {t('inputs.username.label')}{' '}
            <span className={'text-danger'}>*</span>
          </span>
        }
        className={'my-2'}
      >
        <Form.Control
          ref={usernameInput}
          type={'text'}
          placeholder={`${t('inputs.username.label')}}...`}
          value={isModal ? (username as string) : undefined}
          required
          autoFocus={!isModal}
          disabled={isModal}
        />
        <Form.Control.Feedback type={'invalid'} className={'text-start'}>
          {t('inputs.username.invalid_text')}
        </Form.Control.Feedback>
      </FloatingLabel>
      <FloatingLabel
        controlId={'password-input'}
        label={
          <span>
            {t('inputs.password.label')}{' '}
            <span className={'text-danger'}>*</span>
          </span>
        }
        className={'my-2'}
      >
        <Form.Control
          ref={passwordInput}
          type={'password'}
          placeholder={`${t('inputs.password.label')}...`}
          required
          autoFocus={isModal}
        />
        <Form.Control.Feedback type={'invalid'} className={'text-start'}>
          {t('inputs.password.invalid_text')}
        </Form.Control.Feedback>
      </FloatingLabel>
      <FloatingLabel
        controlId={'domain-input'}
        label={`${t('inputs.domain.label')}`}
        className={'my-2'}
      >
        <Form.Control
          ref={domainInput}
          type={'text'}
          placeholder={`${t('inputs.domain.label')}...`}
          isValid={validated && showEmptyDomainFeedback}
          onChange={(event) => {
            setShowEmptyDomainFeedback(String(event.target.value).length === 0);
          }}
        />
        {showEmptyDomainFeedback && (
          <Form.Control.Feedback type={'valid'} className={'text-start'}>
            {t('inputs.domain.valid_text')}
          </Form.Control.Feedback>
        )}
      </FloatingLabel>
    </>
  );

  return (
    <Form noValidate validated={validated} onSubmit={handleSubmit}>
      {isModal ? (
        <>
          <Modal.Body>
            <p className={'text-start'}>{modalProps?.subtitle}</p>
            {InputControls}
          </Modal.Body>
          <Modal.Footer>
            {buttons.cancel.element}
            {buttons.login.element}
          </Modal.Footer>
        </>
      ) : (
        <>
          {InputControls}
          {buttons.login.element}
        </>
      )}
    </Form>
  );
};
