// Copyright 2020 Northern.tech AS
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
import { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Navigate, useParams } from 'react-router';

import { ChevronRight, InfoOutlined as InfoIcon } from '@mui/icons-material';
import { Button, Tooltip, Typography, formControlClasses, typographyClasses } from '@mui/material';
import { makeStyles } from 'tss-react/mui';

import { DOCSTIPS, DocsTextLink } from '@northern.tech/common-ui/DocsLink';
import Loader from '@northern.tech/common-ui/Loader';
import storeActions from '@northern.tech/store/actions';
import { TIMEOUTS } from '@northern.tech/store/constants';
import { getRecaptchaKey } from '@northern.tech/store/selectors';
import { createOrganizationTrial } from '@northern.tech/store/thunks';
import { stringToBoolean } from '@northern.tech/utils/helpers';
import Cookies from 'universal-cookie';

import LoginLogo from '../../../assets/img/loginlogo.svg';
import SignupHero from '../../../assets/img/signuphero.svg';
import { EntryLink } from './Login';
import type { OrgData } from './signup-steps/OrgdataEntry';
import { OrgDataEntry } from './signup-steps/OrgdataEntry';
import type { UserData } from './signup-steps/UserdataEntry';
import { UserDataEntry } from './signup-steps/UserdataEntry';
import { getCurrentLocation, locationMap } from './utils';

const { setSnackbar } = storeActions;

const cookies = new Cookies();

const inputWidth = 400;
const useStyles = makeStyles()(theme => ({
  background: {
    width: '100%',
    marginTop: -(40 + theme.mixins.toolbar.minHeight),
    height: `calc(100vh - ${theme.mixins.toolbar.minHeight}px)`,
    [`.${formControlClasses.root}`]: {
      marginTop: 0
    }
  },
  content: {
    paddingTop: theme.mixins.toolbar.minHeight,
    display: 'grid',
    gridTemplateColumns: 'minmax(min-content, 500px)',
    placeContent: 'center',
    '.entry-link': { marginTop: 0 }
  },
  docsLink: {
    color: theme.palette.common.white,
    '&:hover': { color: theme.palette.common.white },
    [`.${typographyClasses.root}`]: { color: theme.palette.common.white }
  },
  header: { '>svg': { maxHeight: 50 }, zIndex: 1 },
  infoIcon: { color: theme.palette.action.active, zIndex: 100 },
  locationIcon: { transform: 'scale(0.75)' },
  userData: {
    display: 'grid',
    justifyContent: 'center',
    alignContent: 'center',
    '> button': { width: inputWidth }
  },
  orgData: {
    alignItems: 'start',
    display: 'grid',
    placeContent: 'center',
    gridTemplateColumns: inputWidth,
    '.button-wrapper': { width: '100%', 'button': { width: '100%' } }
  },
  promo: {
    background: theme.palette.grey[100],
    gridTemplateRows: 'min-content min-content min-content'
  }
}));

export const LocationWarning = () => {
  const { classes } = useStyles();
  const location = getCurrentLocation(window.location);
  const { icon: Icon, title, fallback } = locationMap[location];
  return (
    <div className="flexbox align-items-center">
      <Icon className={classes.locationIcon} />
      <Typography variant="body2">You are creating your account on the {title} server.</Typography>
      <Tooltip
        arrow
        title={
          <>
            This choice determines where your account data will be stored and which regional data laws will apply.{' '}
            <DocsTextLink className={classes.docsLink} id={DOCSTIPS.hostedRegions.id} typographyProps={{ variant: 'caption' }} />
          </>
        }
      >
        <InfoIcon className={`margin-left-x-small ${classes.infoIcon}`} fontSize="small" />
      </Tooltip>
      <Button className="margin-left-x-small" component="a" href={`https://${fallback.location}/ui/`} endIcon={<ChevronRight />} size="small" variant="text">
        Change to {fallback.title}
      </Button>
    </div>
  );
};

type FormData = UserData & OrgData;

const defaultValues: FormData = { email: '', tos: false, marketing: false, name: '', location: '', captcha: '', password_confirmation: '', password: '' };

export const Signup = () => {
  const [isStarting, setIsStarting] = useState(true);
  const [emailVerified, setEmailVerified] = useState(false);
  const [loading, setLoading] = useState(false);
  const [oauthProvider, setOauthProvider] = useState(undefined);
  const [oauthId, setOauthId] = useState('');
  const [redirectOnLogin, setRedirectOnLogin] = useState(false);
  const [captchaTimestamp, setCaptchaTimestamp] = useState(0);
  const [formValues, setFormValues] = useState<FormData>({ ...defaultValues });

  const { campaign = '' } = useParams();
  const currentUserId = useSelector(state => state.users.currentUserId);
  const recaptchaSiteKey = useSelector(getRecaptchaKey);
  const dispatch = useDispatch();
  const { classes } = useStyles();

  const dispatchedSetSnackbar = useCallback(message => dispatch(setSnackbar(message)), [dispatch]);

  useEffect(() => {
    const usedOauthProvider = cookies.get('oauth');
    if (usedOauthProvider) {
      setOauthProvider(usedOauthProvider);
      setOauthId(`${cookies.get('externalID')}`);
      setFormValues(current => ({ ...current, email: cookies.get('email') }));
      setEmailVerified(stringToBoolean(cookies.get('emailVerified')));
      setIsStarting(false);
    }
    const location = getCurrentLocation(window.location);
    setFormValues(current => ({ ...current, location }));
  }, []);

  useEffect(() => {
    if (currentUserId) {
      dispatchedSetSnackbar('');
      setRedirectOnLogin(true);
    }
  }, [currentUserId, dispatchedSetSnackbar]);

  const handleSignup = (formData: OrgData) => {
    if (recaptchaSiteKey !== '' && formData.captcha === '') {
      return setSnackbar({ message: 'Please complete the reCAPTCHA test before proceeding!', autoHideDuration: TIMEOUTS.fiveSeconds, action: '' });
    }
    setLoading(true);
    const { name, captcha, tos: _tos, ...remainder } = formData;
    const { email, password } = formValues;
    const credentials = oauthProvider ? { email, login: { [oauthProvider]: oauthId } } : { email, password };
    const signup = {
      ...remainder,
      ...credentials,
      'g-recaptcha-response': captcha || 'empty',
      campaign,
      organization: name,
      plan: 'enterprise',
      ts: captchaTimestamp
    };
    return dispatch(createOrganizationTrial(signup))
      .unwrap()
      .catch(() => {
        setFormValues({ ...formValues, ...formData, captcha: '' });
        setIsStarting(true);
        setLoading(false);
      });
  };

  const onUserDataSubmit = (formData: UserData) => {
    setFormValues({ ...formValues, ...formData });
    setEmailVerified(true);
    setIsStarting(false);
  };

  if (redirectOnLogin) {
    return <Navigate to="/" replace />;
  }
  return (
    <>
      <div className="two-columns" style={{ zIndex: 100 }}>
        <div className={`flexbox align-items-center space-between margin-left-x-large margin-top-large ${classes.header}`}>
          <LoginLogo />
          {isStarting && <LocationWarning />}
        </div>
      </div>
      <div className={`${classes.background} ${isStarting ? 'two-columns' : classes.orgData}`} id="signup-box">
        <div className={classes.content}>
          {loading ? (
            <Loader show style={{ marginTop: '40vh' }} />
          ) : (
            <>
              {isStarting ? (
                <UserDataEntry classes={classes} onSubmit={onUserDataSubmit} />
              ) : (
                <OrgDataEntry
                  classes={classes}
                  emailVerified={emailVerified}
                  handleSignup={handleSignup}
                  initialValues={{ tos: formValues.tos, location: formValues.location, marketing: formValues.marketing, name: formValues.name, captcha: '' }}
                  loading={loading}
                  recaptchaSiteKey={recaptchaSiteKey}
                  setCaptchaTimestamp={setCaptchaTimestamp}
                />
              )}
              <EntryLink className={isStarting ? '' : 'entry-link'} target="login" />
            </>
          )}
        </div>
        {isStarting && (
          <div className={`${classes.content} ${classes.promo}`}>
            <Typography className="margin-bottom" variant="h5">
              Try Mender for free for 12 months – no credit card required.
            </Typography>
            <Typography>
              Mender provides a complete over-the-air update infrastructure for all device software. Whether in the field or the factory, you can remotely and
              easily manage device software without the need for manual labor.
            </Typography>
            <div className="svg-container margin-top-large">
              <SignupHero />
            </div>
          </div>
        )}
      </div>
    </>
  );
};

export default Signup;
