import {
  selectEmail,
  selectFormValid,
  selectPassword,
  selectStatusIsLoading,
  useAuthStore,
} from "../../model";
import {
  type SubmitEvent,
  type ChangeEvent,
  type HTMLAttributes,
  type InputHTMLAttributes,
  type ButtonHTMLAttributes,
  cloneElement,
  type ReactElement,
} from "react";

export type InputAttributes = InputHTMLAttributes<HTMLInputElement>;
export type ButtonAttributes = ButtonHTMLAttributes<HTMLButtonElement>;

export interface Props {
  InputComponent?: ReactElement<InputAttributes>;
  ButtonComponent?: ReactElement<ButtonAttributes>;
}

const DefaultInputComponent = ({
  value,
  onChange,
  ["aria-label"]: ariaLabel,
}: InputAttributes) => (
  <input
    type="email"
    value={value}
    onChange={onChange}
    aria-label={ariaLabel}
  />
);

const DefaultButtonComponent = ({ disabled }: ButtonAttributes) => (
  <button type="submit" disabled={disabled} />
);

/**
 * Login form component
 */
export function LoginForm({ InputComponent, ButtonComponent }: Props) {
  const { setEmail, setPassword, login } = useAuthStore();
  const email = useAuthStore(selectEmail);
  const password = useAuthStore(selectPassword);
  const formValid = useAuthStore(selectFormValid);
  const isLoading = useAuthStore(selectStatusIsLoading);

  const disabled = !formValid || isLoading;

  const handleEmailChange = (e: ChangeEvent<HTMLInputElement>) => {
    setEmail(e.target.value);
  };

  const handlePasswordChange = (e: ChangeEvent<HTMLInputElement>) => {
    setPassword(e.target.value);
  };

  const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {
    e.preventDefault();
    login();
  };

  return (
    <form aria-label="Login form" onSubmit={handleSubmit}>
      {InputComponent ? (
        cloneElement(InputComponent, {
          type: "email",
          value: email,
          onChange: handleEmailChange,
          "aria-label": "Email",
        })
      ) : (
        <DefaultInputComponent
          type="email"
          value={email}
          onChange={handleEmailChange}
          aria-label="Email"
        />
      )}
      {InputComponent ? (
        cloneElement(InputComponent, {
          type: "password",
          value: password,
          onChange: handlePasswordChange,
          "aria-label": "Password",
        })
      ) : (
        <DefaultInputComponent
          type="password"
          value={password}
          onChange={handlePasswordChange}
          aria-label="Password"
        />
      )}
      {ButtonComponent ? (
        cloneElement(ButtonComponent, {
          type: "submit",
          disabled: disabled,
          children: "Login",
        })
      ) : (
        <DefaultButtonComponent type="submit" disabled={disabled}>
          Login
        </DefaultButtonComponent>
      )}
    </form>
  );
}
