import { observer } from 'mobx-react';
import { Button, ButtonLogin, mergeStyles, useApphouse } from '..';
import { ISignInFields } from '../components/Form/SignInForm';
import { AppStoreWithUser } from './AppStoreWithUser';
import React from 'react';
import { ButtonStyles } from '../components/Button';
import { ApphouseComponent } from '../components/component.interfaces';
import { IoMdLogOut } from 'react-icons/io';

export interface RestrictedAreaStyles {
  signOutButton?: ButtonStyles;
  signInButton?: ButtonStyles;
}

export interface RestrictedAreaProps
  extends ApphouseComponent<RestrictedAreaStyles> {
  /**
   * The content to be displayed if the user is authorized and signed in
   * @required
   */
  children: React.ReactNode;
  /**
   * A boolean value that determines if the sign out button should be shown.
   * This button will be displayed at the top right corner of the screen
   * @default false
   * @optional
   */
  showSignOutButton?: boolean;
  /**
   * A boolean value that determines if the sign in button should be shown.
   * This button will be displayed at the top right corner of the screen
   * @default false
   * @optional
   */
  showSignInButton?: boolean;
  /**
   * if true, the sign in and sign up buttons will always be visible on the top right
   * corner of the screen.
   * @default false - the buttons will flow with the content
   */
  stickyButtons?: boolean;
}

/**
 * A component that restricts the content to be displayed to only
 * authorized users. This component renders a sign in button that will
 * trigger a popup with the sign in form if the user is not signed in
 * and a sign up form if the user is not signed up.
 *
 * @param props RestrictedAreaProps
 */
export const RequiresFirebaseAuthentication = observer(
  (props: RestrictedAreaProps) => {
    const {
      children,
      showSignOutButton,
      showSignInButton,
      styleOverwrites = {},
      stickyButtons = false
    } = props;
    const { isAuthorized, user, app, theme } = useApphouse<AppStoreWithUser>();
    const errorMessage = user?.errorMessage;
    const zIndex = (theme.tokens.zIndex?.popup || 1000) + 1;
    const buttonPosition = stickyButtons ? 'fixed' : 'absolute';
    const componentStyles: RestrictedAreaStyles = {
      signOutButton: {
        position: buttonPosition,
        top: '0.5rem',
        right: '0.5rem',
        zIndex: zIndex
      },
      signInButton: {
        position: buttonPosition,
        top: '0.5rem',
        right: '0.5rem',
        zIndex: zIndex
      }
    };

    const localStyles = mergeStyles(componentStyles, styleOverwrites);

    const onSignIn = async (formData: ISignInFields) => {
      const status = await user?.signIn(formData.email, formData.password);
      if (!status) {
        app.feedback.setFeedback({
          message: `Invalid credentials ${user.errorMessage}`,
          variant: 'error'
        });
      } else {
        app.feedback.setFeedback({
          message: `Signed in successfully`,
          variant: 'success'
        });
        app.popups.clear();
      }
    };

    const onSignUp = (formData: ISignInFields) => {
      const status = user?.signupWithEmailAndPassword(
        formData.email,
        formData.password
      );
      if (!status) {
        app.feedback.setFeedback({
          message: `Error creating account ${user.errorMessage}`,
          variant: 'error'
        });
      } else {
        app.feedback.setFeedback({
          message: `Account created successfully`,
          variant: 'success'
        });
        app.popups.clear();
      }
    };

    if (!isAuthorized && showSignInButton) {
      return (
        <ButtonLogin
          onSignIn={onSignIn}
          onSignUp={onSignUp}
          errorMessage={errorMessage}
          styleOverwrites={localStyles.signInButton}
        />
      );
    }

    if (isAuthorized) {
      return (
        <React.Fragment>
          {showSignOutButton && (
            <Button
              variant="clear"
              onClick={() => {
                user.logout();
              }}
              styleOverwrites={localStyles.signOutButton}
            >
              Sign out <IoMdLogOut size={theme.tokens.iconSize.s} />
            </Button>
          )}
          {children}
        </React.Fragment>
      );
    }

    return null;
  }
);
