// Copyright 2016 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 } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { ChevronRight } from '@mui/icons-material';
import { Button, Typography } from '@mui/material';
import { makeStyles } from 'tss-react/mui';

import LinedHeader from '@northern.tech/common-ui/LinedHeader';
import { Link } from '@northern.tech/common-ui/Link';
import storeActions from '@northern.tech/store/actions';
import { getToken } from '@northern.tech/store/auth';
import { TIMEOUTS, useradmApiUrl } from '@northern.tech/store/constants';
import { getCurrentUser, getFeatures, getIsEnterprise } from '@northern.tech/store/selectors';
import { loginUser, logoutUser } from '@northern.tech/store/thunks';
import { clearAllRetryTimers } from '@northern.tech/utils/retrytimer';
import Cookies from 'universal-cookie';

import LoginLogo from '../../../assets/img/loginlogo.svg';
import VeryMuch from '../../../assets/img/verymuch.svg';
import { LoginForm } from './LoginForm';
import { OAuth2Providers } from './OAuth2Providers';
import { getCurrentLocation, locationMap } from './utils';

const { setSnackbar } = storeActions;

const cookies = new Cookies();

const useStyles = makeStyles()(theme => {
  const skew = 3;
  const backgroundRadius = 100;
  return {
    entryLink: {
      color: theme.palette.background.paper,
      a: { color: theme.palette.text.entryLink }
    },
    reset: {
      transform: `skew(0, ${skew}deg)`,
      'svg': { maxWidth: 200 },
      '#login-logo path': { fill: theme.palette.background.paper },
      '#login-box': {
        background: theme.palette.background.paper,
        minWidth: 'calc(100% + 20px)',
        maxWidth: 480,
        paddingBottom: 25,
        paddingRight: 50,
        paddingLeft: 50,
        borderRadius: 10
      }
    },
    background: {
      background: '#284d68', // a specific dark blue, unrelated to other brand colours
      padding: '40px 65px',
      borderTopLeftRadius: backgroundRadius,
      borderBottomRightRadius: backgroundRadius,
      marginBottom: 60,
      marginTop: 30,
      transform: `skew(0, -${skew}deg)`,
      zIndex: 1
    },
    ntBranding: { bottom: `calc(${theme.mixins.toolbar.minHeight}px + 3vh)`, right: 0, zIndex: 0 }
  };
});

const entryText = {
  signup: { linkText: 'Sign up here', question: `Don't have an account?`, target: '/signup' },
  login: { linkText: 'Log in', question: `Already have an account?`, target: '/login' }
};

export const EntryLink = ({ className = '', target = 'signup' }) => (
  <div className={`margin-top-small margin-bottom flexbox centered ${className}`}>
    <Typography className="margin-right-x-small">{entryText[target].question}</Typography>
    <Button component={Link} className="flexbox align-items-center" to={entryText[target].target} variant="text" endIcon={<ChevronRight fontSize="small" />}>
      {entryText[target].linkText}
    </Button>
  </div>
);

export const LocationWarning = () => {
  const location = getCurrentLocation(window.location);
  const { icon: Icon, title, fallback } = locationMap[location];
  return (
    <div className="flexbox centered margin-top-large">
      <Icon />
      <div className="margin-left-small">
        You are logging into the <b style={{ marginLeft: 4 }}>{title} server</b>.
      </div>
      <Link className="flexbox align-items-center margin-left-small" href={`https://${fallback.location}/ui/`} external>
        Change to {fallback.title} <ChevronRight fontSize="small" />
      </Link>
    </div>
  );
};

export const OAuthHeader = ({ buttonProps, type }) => (
  <>
    <Typography variant="subtitle1" className="flexbox centered margin-bottom-small">
      {type} with:
    </Typography>
    <div className="flexbox centered">
      {OAuth2Providers.map(provider => {
        const props = buttonProps ? buttonProps : { href: `${useradmApiUrl}/oauth2/${provider.id}` };
        return (
          <Button
            className="margin-left-x-small margin-right-x-small"
            variant="outlined"
            color="neutral"
            key={provider.id}
            startIcon={provider.icon}
            {...props}
          >
            {provider.name}
          </Button>
        );
      })}
    </div>
    <LinedHeader className="margin-top-large flexbox centered" heading="or your email address" innerStyle={{ padding: 15, top: -24, fontWeight: 'bold' }} />
  </>
);

export const Login = () => {
  const dispatch = useDispatch();
  const currentUser = useSelector(getCurrentUser);
  const { isHosted } = useSelector(getFeatures);
  const isEnterprise = useSelector(getIsEnterprise);
  const { classes } = useStyles();

  useEffect(() => {
    clearAllRetryTimers(message => dispatch(setSnackbar(message)));
    if (getToken()) {
      dispatch(logoutUser());
    }
    const loginError = cookies.get('error');
    if (loginError) {
      dispatch(setSnackbar({ message: loginError, autoHideDuration: TIMEOUTS.refreshDefault }));
      cookies.remove('error');
    }
    return () => {
      dispatch(setSnackbar(''));
    };
  }, [dispatch]);

  useEffect(() => {
    if (currentUser.id) {
      dispatch(setSnackbar(''));
    }
  }, [currentUser, dispatch]);

  const onLoginClick = useCallback(
    ({ noExpiry, ...loginData }) =>
      // set no expiry in localstorage to remember checkbox value and avoid any influence of expiration time that might occur with cookies
      dispatch(loginUser({ ...loginData, stayLoggedIn: noExpiry })).unwrap(),
    [dispatch]
  );

  const onOAuthClick = ({ target: { textContent } }) => {
    const providerId = OAuth2Providers.find(provider => provider.name === textContent).id;
    const oauthTimeout = new Date();
    oauthTimeout.setDate(oauthTimeout.getDate() + 7);
    window.localStorage.setItem('oauth', `${oauthTimeout.getTime()}`);
    window.location.replace(`${useradmApiUrl}/oauth2/${providerId}`);
  };

  return (
    <>
      {isHosted ? <LocationWarning /> : <div />}
      <div className={`content ${classes.background}`}>
        <div className={`flexbox column centered ${classes.reset}`}>
          <LoginLogo alt="mender-logo" id="login-logo" className="margin-bottom" />
          <div className="flexbox column" id="login-box">
            <Typography className="flexbox centered margin-top margin-bottom-small" variant="h5">
              Welcome back!
            </Typography>
            {isHosted && <OAuthHeader type="Log in" buttonProps={{ onClick: onOAuthClick }} />}
            <LoginForm isEnterprise={isEnterprise} isHosted={isHosted} onSubmit={onLoginClick} />
          </div>
          {isHosted ? <EntryLink className={classes.entryLink} target="signup" /> : <div className="padding" />}
        </div>
      </div>
      <VeryMuch className={`absolute ${classes.ntBranding}`} />
    </>
  );
};

export default Login;
