import { useState, useCallback } from 'react';
import { styled } from '@mui/material/styles';
import { useTranslation } from 'react-i18next';
import { Navigate } from 'react-router-dom';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';

import { RegistrationDialog, RequestPasswordResetDialog, ResetPasswordDialog, AccountActivationDialog } from '@app/dialogs';
import { LanguageDropdown } from '@app/components';
import { LoginForm } from '@app/forms';
import { useReduxEffect, useFireOnce, useWebClient } from '@app/hooks';
import { Images } from '@app/images';
import { HostDTO, serverProps } from '@app/services';
import { App, Enriched } from '@app/types';
import { ServerSelectors, ServerTypes } from '@app/store';
import Layout from '../Layout/Layout';
import { useAppSelector } from '@app/store';

import './Login.css';
import { useToast } from '@app/components';

const PREFIX = 'Login';

const classes = {
  root: `${PREFIX}-root`
};

const Root = styled('div')(({ theme }) => ({
  [`&.${classes.root}`]: {
    '& .login-content__header': {
      color: theme.palette.success.light
    },

    '& .login-content__description': {
      backgroundColor: theme.palette.primary.main,
      color: theme.palette.primary.contrastText,
    },

    '& .login-content__description-bar': {
      backgroundColor: theme.palette.primary.dark,
    },

    '& .login-content__description-cards__card': {
      backgroundColor: theme.palette.background.paper,
      color: theme.palette.primary.main,
    },

    [theme.breakpoints.up('lg')]: {
      '& .login-content': {
        maxWidth: '1000px',
      },

      '& .login-content__form': {
        width: '50%',
      },

      '& .login-content__description': {
        width: '50%',
        display: 'flex',
      },
    },
  }
}));

const Login = () => {
  const description = useAppSelector(s => ServerSelectors.getDescription(s));
  const isConnected = useAppSelector(ServerSelectors.getIsConnected);
  const webClient = useWebClient();
  const { t } = useTranslation();

  const [pendingActivationOptions, setPendingActivationOptions] = useState<Enriched.PendingActivationContext | null>(null);

  const [rememberLogin, setRememberLogin] = useState(null);
  const [dialogState, setDialogState] = useState({
    passwordResetRequestDialog: false,
    resetPasswordDialog: false,
    registrationDialog: false,
    activationDialog: false,
  });
  const [userToResetPassword, setUserToResetPassword] = useState(null);

  const passwordResetToast = useToast({ key: 'password-reset-success', children: t('LoginContainer.toasts.passwordResetSuccess') });
  const accountActivatedToast = useToast({
    key: 'account-activation-success',
    children: t('LoginContainer.toasts.accountActivationSuccess')
  });

  useReduxEffect(() => {
    closeRequestPasswordResetDialog();
    openResetPasswordDialog();
  }, ServerTypes.RESET_PASSWORD_REQUESTED, []);

  useReduxEffect(() => {
    passwordResetToast.openToast()
    closeResetPasswordDialog();
  }, ServerTypes.RESET_PASSWORD_SUCCESS, []);

  useReduxEffect(() => {
    accountActivatedToast.openToast()
    closeActivateAccountDialog();
    setPendingActivationOptions(null);
  }, ServerTypes.ACCOUNT_ACTIVATION_SUCCESS, []);

  useReduxEffect(({ payload: { options } }) => {
    setPendingActivationOptions(options);
    closeRegistrationDialog();
    openActivateAccountDialog();
  }, ServerTypes.ACCOUNT_AWAITING_ACTIVATION, []);

  useReduxEffect(() => {
    resetSubmitButton();
  }, [ServerTypes.CONNECTION_FAILED, ServerTypes.LOGIN_FAILED], []);

  useReduxEffect(({ payload: { options: { hashedPassword } } }) => {
    updateHost(hashedPassword, rememberLogin);
  }, ServerTypes.LOGIN_SUCCESSFUL, [rememberLogin]);

  const showDescription = () => {
    return !isConnected && description?.length;
  };

  const onSubmitLogin = useCallback((loginForm) => {
    setRememberLogin(loginForm);
    const { userName, password, selectedHost, remember } = loginForm;

    const options: Omit<Enriched.LoginConnectOptions, 'reason'> = {
      ...App.getHostPort(selectedHost),
      userName,
      password,
    };

    if (remember && !password) {
      options.hashedPassword = selectedHost.hashedPassword;
    }

    webClient.request.authentication.login(options);
  }, []);

  const [submitButtonDisabled, resetSubmitButton, handleLogin] = useFireOnce(onSubmitLogin);

  const updateHost = (hashedPassword, { selectedHost, remember, userName }) => {
    HostDTO.get(selectedHost.id).then(hostDTO => {
      hostDTO.remember = remember;
      hostDTO.userName = remember ? userName : null;
      hostDTO.hashedPassword = remember ? hashedPassword : null;

      hostDTO.save();
    });
  };

  const handleRegistrationDialogSubmit = (registerForm) => {
    setRememberLogin(registerForm);
    const { userName, password, email, country, realName, selectedHost } = registerForm;

    webClient.request.authentication.register({
      ...App.getHostPort(selectedHost),
      userName,
      password,
      email,
      country,
      realName,
    });
  };

  const handleAccountActivationDialogSubmit = ({ token }) => {
    if (!pendingActivationOptions) {
      return;
    }
    webClient.request.authentication.activateAccount({
      host: pendingActivationOptions.host,
      port: pendingActivationOptions.port,
      userName: pendingActivationOptions.userName,
      token,
    });
  };

  const handleRequestPasswordResetDialogSubmit = (form) => {
    const { userName, email, selectedHost } = form;
    const { host, port } = App.getHostPort(selectedHost);

    if (email) {
      webClient.request.authentication.resetPasswordChallenge({ userName, email, host, port });
    } else {
      setUserToResetPassword(userName);
      webClient.request.authentication.resetPasswordRequest({ userName, host, port });
    }
  };

  const handleResetPasswordDialogSubmit = ({ userName, token, newPassword, selectedHost }) => {
    const { host, port } = App.getHostPort(selectedHost);

    webClient.request.authentication.resetPassword({ userName, token, newPassword, host, port });
  };

  const skipTokenRequest = (userName) => {
    setUserToResetPassword(userName);

    setDialogState(s => ({ ...s,
      passwordResetRequestDialog: false,
      resetPasswordDialog: true,
    }));
  };

  const closeRequestPasswordResetDialog = () => {
    setDialogState(s => ({ ...s, passwordResetRequestDialog: false }));
  }

  const openRequestPasswordResetDialog = () => {
    setDialogState(s => ({ ...s, passwordResetRequestDialog: true }));
  }

  const closeResetPasswordDialog = () => {
    setDialogState(s => ({ ...s, resetPasswordDialog: false }));
  }

  const openResetPasswordDialog = () => {
    setDialogState(s => ({ ...s, resetPasswordDialog: true }));
  }

  const closeRegistrationDialog = () => {
    setDialogState(s => ({ ...s, registrationDialog: false }));
  }

  const openRegistrationDialog = () => {
    setDialogState(s => ({ ...s, registrationDialog: true }));
  }

  const closeActivateAccountDialog = () => {
    setDialogState(s => ({ ...s, activationDialog: false }));
  };

  const openActivateAccountDialog = () => {
    setDialogState(s => ({ ...s, activationDialog: true }));
  };

  return (
    <Layout showNav={false} noHeightLimit={true}>
      <Root className={'login overflow-scroll ' + classes.root}>
        { isConnected && <Navigate to={App.RouteEnum.SERVER} />}

        <div className="login__wrapper">
          <Paper className="login-content">
            <div className="login-content__form">
              <div className="login-content__header">
                <img src={Images.Logo} alt="logo" />
                <span>COCKATRICE</span>
              </div>
              <Typography variant="h1">{ t('LoginContainer.header.title') }</Typography>
              <Typography variant="subtitle1">{ t('LoginContainer.header.subtitle') }</Typography>
              <div className="login-form">
                <LoginForm
                  onSubmit={handleLogin}
                  onResetPassword={openRequestPasswordResetDialog}
                  disableSubmitButton={submitButtonDisabled}
                />
              </div>

              {
                showDescription() && (
                  <Paper className="login-content__connectionStatus">
                    {description}
                  </Paper>
                )
              }

              <div className="login-footer">
                <div className="login-footer__register">
                  <span>{ t('LoginContainer.footer.registerPrompt') }</span>
                  <Button color="primary" onClick={openRegistrationDialog}>{ t('LoginContainer.footer.registerAction') }</Button>
                </div>
                <Typography variant="subtitle2">
                  { t('LoginContainer.footer.credit') } - { new Date().getUTCFullYear() }
                </Typography>

                {
                  serverProps.REACT_APP_VERSION && (
                    <Typography variant="subtitle2">
                      { t('LoginContainer.footer.version') }: { serverProps.REACT_APP_VERSION }
                    </Typography>
                  )
                }

                <div className="login-footer__language">
                  <LanguageDropdown />
                </div>
              </div>
            </div>
            <div className="login-content__description">
              <div className="login-content__description-graphics">
                <div className="topLeft login-content__description-square" />
                <div className="topRight login-content__description-square" />
                <div className="bottomRight login-content__description-square" />
                <div className="bottomLeft login-content__description-square" />
                <div className="topBar login-content__description-bar" />
                <div className="bottomBar login-content__description-bar" />
              </div>
              <div className="login-content__description-wrapper">
                <div className="login-content__description-cards">
                  <div className="login-content__description-cards__card leftCard">
                    <div className="login-content__description-cards__card-wrapper">
                      <img src={Images.Faces.face1} alt='Stock Player' />
                      <span>1mrlee</span>
                    </div>
                  </div>
                  <div className="login-content__description-cards__card rightCard">
                    <div className="login-content__description-cards__card-wrapper">
                      <img src={Images.Faces.face2} alt='Stock Player' />
                      <span>CyberX</span>
                    </div>
                  </div>
                  <div className="login-content__description-cards__card topCard">
                    <div className="login-content__description-cards__card-wrapper">
                      <img src={Images.Faces.face3} alt='Stock Player' />
                      <span>Gamer69</span>
                    </div>
                  </div>
                </div>
                { /*<img src={loginGraphic} className="login-content__description-image"/>*/}
                <p className="login-content__description-subtitle1">{ t('LoginContainer.content.subtitle1') }</p>
                <p className="login-content__description-subtitle2">{ t('LoginContainer.content.subtitle2') }</p>
              </div>
            </div>
          </Paper>
        </div>

        <RegistrationDialog
          isOpen={dialogState.registrationDialog}
          onSubmit={handleRegistrationDialogSubmit}
          handleClose={closeRegistrationDialog}
        />

        <RequestPasswordResetDialog
          isOpen={dialogState.passwordResetRequestDialog}
          onSubmit={handleRequestPasswordResetDialogSubmit}
          handleClose={closeRequestPasswordResetDialog}
          skipTokenRequest={skipTokenRequest}
        />

        <ResetPasswordDialog
          isOpen={dialogState.resetPasswordDialog}
          onSubmit={handleResetPasswordDialogSubmit}
          handleClose={closeResetPasswordDialog}
          userName={userToResetPassword}
        />

        <AccountActivationDialog
          isOpen={dialogState.activationDialog}
          onSubmit={handleAccountActivationDialogSubmit}
          handleClose={closeActivateAccountDialog}
        />
      </Root>
    </Layout>
  );
}

export default Login;
