import {useEffect, useState, forwardRef} from 'react'
import {signIn} from 'next-auth/react'
import {useRouter} from 'next/router'
import PropTypes from 'prop-types'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Container from '@mui/material/Container'
import FormControl from '@mui/material/FormControl'
import IconButton from '@mui/material/IconButton'
import Input from '@mui/material/Input'
import InputAdornment from '@mui/material/InputAdornment'
import InputLabel from '@mui/material/InputLabel'
import LinearProgress from '@mui/material/LinearProgress'
import Snackbar from '@mui/material/Snackbar'
import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs'
import Typography from '@mui/material/Typography'
import Visibility from '@mui/icons-material/Visibility'
import VisibilityOff from '@mui/icons-material/VisibilityOff'
import MuiAlert from '@mui/material/Alert'
import LoginIcon from '@mui/icons-material/Login'
import AppRegistrationRoundedIcon from '@mui/icons-material/AppRegistrationRounded'
import axios from 'axios'

import {validateEmail} from '../../lib/utils/emails'
import ResetPassword from '../password/reset-password'
import ResetDialog from '../password/reset-dialog'

const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:1337'

function TabPanel(props) {
  const {children, value, index, ...other} = props

  return (
    <div
      role='tabpanel'
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box sx={{p: 3}}>
          {children}
        </Box>
      )}
    </div>
  )
}

TabPanel.propTypes = {
  children: PropTypes.node,
  index: PropTypes.number.isRequired,
  value: PropTypes.number.isRequired,
}

function a11yProps(index) {
  return {
    id: `simple-tab-${index}`,
    'aria-controls': `simple-tabpanel-${index}`,
  }
}

const Alert = forwardRef(function Alert(props, ref) {
  return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
})

function Koneksyon({chimen}) {
  const [error, setError] = useState('')
  const [loginCredentials, setLoginCredentials] = useState({username: '', password: ''})
  const [registerCredentials, setRegisterCredentials] = useState({username: '', email: '', password: ''})
  const [passwordVerification, setPasswordVerification] = useState('')
  const [showPassword, setShowPassword] = useState(false)
  const [showRegisterPassword, setShowRegisterPassword] = useState(false)
  const [showVerificationPassword, setShowVerificationPassword] = useState(false)
  const [loading, setLoading] = useState(false)
  const [open, setOpen] = useState(true)
  const [success, setSuccess] = useState(false)
  const [openDialog, setOpenDialog] = useState(false)
  const [value, setValue] = useState(0)
  const router = useRouter()

  const handleUpdate = update => {
    setLoginCredentials({...loginCredentials, ...update})
  }

  const handleRegisterUpdate = update => {
    setRegisterCredentials({...registerCredentials, ...update})
  }

  const handleChange = (event, newValue) => {
    setValue(newValue)
  }

  const register = async () => {
    try {
      const response = await axios.post(`${apiUrl}/auth/local/register`, {
        ...registerCredentials
      }, {
        headers: {
          'content-type': 'application/json'
        }
      })
      localStorage.setItem('username', `${response?.data?.user?.username}`)
      setSuccess(true)
      resetRegisterForm()
    } catch (error_) {
      if (error_.message.endsWith(400)) {
        setError('E-mail ou utilisateur déjà enregistré')
      } else {
        setError('Une erreur s’est produite')
      }
    }
  }

  const resetRegisterForm = () => {
    setRegisterCredentials({username: '', email: '', password: ''})
    setPasswordVerification('')
  }

  const handleClickLogin = async () => {
    if (!validateEmail(loginCredentials.username) || loginCredentials.password === '') {
      return
    }

    setLoading(true)
    const response = await signIn('credentials', {
      callbackUrl: `${siteUrl}${chimen}`,
      redirect: false,
      ...loginCredentials
    })
    if (response.error) {
      setError(response.error)
      setLoading(false)
    } else if (response.ok) {
      setLoading(false)
      router.push(chimen)
    }
  }

  const handleClickRegister = async () => {
    setLoading(true)
    if (!validateEmail(registerCredentials.email) || registerCredentials.password === '') {
      return
    }

    if (registerCredentials.password !== passwordVerification) {
      setError('Les 2 mots de passe de correspondent pas')
      setLoading(false)
      return
    }

    if (registerCredentials.username.length < 3) {
      setError('Le nom d’utilisateur est trop court, 3 caratères minimum')
      setLoading(false)
      return
    }

    if (registerCredentials.password.length < 6) {
      setError('Le mot de passe est trop court, 6 caratères minimum')
      setLoading(false)
      return
    }

    await register()
    setLoading(false)
  }

  const handleClose = (event, reason) => {
    if (reason === 'clickaway') {
      return
    }

    setOpen(false)
    setSuccess(false)
    setError('')
  }

  useEffect(() => {
    if (error) {
      setOpen(true)
    }

    return () => {
      setLoading(false)
    }
  }, [error])

  const handleClickShowPassword = () => {
    setShowPassword(!showPassword)
  }

  const handleClickShowRegisterPassword = () => {
    setShowRegisterPassword(!showRegisterPassword)
  }

  const handleClickShowVerificationPassword = () => {
    setShowVerificationPassword(!showVerificationPassword)
  }

  const handleMouseDownPassword = event => {
    event.preventDefault()
  }

  const handleMouseDownRegisterPassword = event => {
    event.preventDefault()
  }

  const handleMouseDownVerificationPassword = event => {
    event.preventDefault()
  }

  const handleKeyUpLogin = event => {
    if (event.keyCode === 13) {
      handleClickLogin()
    }
  }

  const handleKeyUpRegister = event => {
    if (event.keyCode === 13) {
      handleClickRegister()
    }
  }

  return (
    <Container sx={{marginTop: 2}} maxWidth='sm'>

      <Box sx={{width: '100%'}}>
        <Tabs centered value={value} aria-label='basic tabs example' onChange={handleChange}>
          <Tab icon={<LoginIcon />} label='Se connecter' {...a11yProps(0)} />
          <Tab icon={<AppRegistrationRoundedIcon />} label='S’inscrire' {...a11yProps(1)} />
        </Tabs>
        <TabPanel value={value} index={0}>
          <FormControl fullWidth autoComplete='off'>
            <InputLabel htmlFor='username'>E-mail</InputLabel>
            <Input
              autoComplete='email'
              value={loginCredentials.username}
              name='username'
              type='email'
              id='email'
              onChange={event => handleUpdate({username: event.target.value})}
              onKeyUp={handleKeyUpLogin}
            />
          </FormControl>

          <FormControl fullWidth style={{marginTop: '1em'}}>
            <InputLabel htmlFor='password'>Mot de passe</InputLabel>
            <Input
              value={loginCredentials.password}
              name='password'
              type={showPassword ? 'text' : 'password'}
              id='password'
              endAdornment={
                <InputAdornment position='end'>
                  <IconButton
                    aria-label='password visibility'
                    size='large'
                    onClick={handleClickShowPassword}
                    onMouseDown={handleMouseDownPassword}
                  >
                    {showPassword ? <Visibility /> : <VisibilityOff />}
                  </IconButton>
                </InputAdornment>
              }
              onChange={event => handleUpdate({password: event.target.value})}
              onKeyUp={handleKeyUpLogin}
            />
          </FormControl>

          <Button
            fullWidth
            disabled={loading || !validateEmail(loginCredentials.username) || loginCredentials.password === ''}
            style={{marginTop: 20}}
            variant='contained'
            color='primary'
            onClick={handleClickLogin}
          >
            <Typography style={{fontWeight: 'bold'}}>
              Connexion
            </Typography>
          </Button>
          <ResetPassword />
        </TabPanel>
        <TabPanel value={value} index={1}>
          <FormControl fullWidth>
            <InputLabel htmlFor='register-email'>E-mail</InputLabel>
            <Input
              autoComplete='email'
              value={registerCredentials.email}
              name='register-email'
              type='email'
              id='register-email'
              onChange={event => handleRegisterUpdate({email: event.target.value})}
              onKeyUp={handleKeyUpRegister}
            />
          </FormControl>
          <FormControl fullWidth style={{marginTop: '1em'}}>
            <InputLabel htmlFor='register-username'>Nom d’utilisateur</InputLabel>
            <Input
              autoComplete='username'
              value={registerCredentials.username}
              name='register-username'
              type='text'
              id='register-username'
              onChange={event => handleRegisterUpdate({username: event.target.value})}
              onKeyUp={handleKeyUpRegister}
            />
          </FormControl>
          <FormControl fullWidth style={{marginTop: '1em'}}>
            <InputLabel htmlFor='password'>Mot de passe</InputLabel>
            <Input
              value={registerCredentials.password}
              name='register-password'
              type={showRegisterPassword ? 'text' : 'password'}
              id='register-password'
              endAdornment={
                <InputAdornment position='end'>
                  <IconButton
                    aria-label='password visibility'
                    size='large'
                    onClick={handleClickShowRegisterPassword}
                    onMouseDown={handleMouseDownRegisterPassword}
                  >
                    {showRegisterPassword ? <Visibility /> : <VisibilityOff />}
                  </IconButton>
                </InputAdornment>
              }
              onChange={event => handleRegisterUpdate({password: event.target.value})}
              onKeyUp={handleKeyUpRegister}
            />
          </FormControl>
          <FormControl fullWidth style={{marginTop: '1em'}}>
            <InputLabel htmlFor='password'>Vérification du mot de passe</InputLabel>
            <Input
              value={passwordVerification}
              name='verification-password'
              type={showVerificationPassword ? 'text' : 'password'}
              id='verification-password'
              error={registerCredentials.password !== passwordVerification}
              endAdornment={
                <InputAdornment position='end'>
                  <IconButton
                    aria-label='password visibility'
                    size='large'
                    onClick={handleClickShowVerificationPassword}
                    onMouseDown={handleMouseDownVerificationPassword}
                  >
                    {showVerificationPassword ? <Visibility /> : <VisibilityOff />}
                  </IconButton>
                </InputAdornment>
              }
              onChange={event => setPasswordVerification(event.target.value)}
              onKeyUp={handleKeyUpRegister}
            />
          </FormControl>
          <Button
            fullWidth
            disabled={loading || !validateEmail(registerCredentials.email) || registerCredentials.username === '' || registerCredentials.password === ''}
            style={{marginTop: 20}}
            variant='contained'
            color='primary'
            onClick={handleClickRegister}
          >
            <Typography style={{fontWeight: 'bold'}}>
              Inscription
            </Typography>
          </Button>
          <Button
            fullWidth
            style={{marginTop: 20}}
            variant='outlined'
            color='warning'
            onClick={() => setOpenDialog(true)}
          >
            <Typography style={{fontWeight: 'bold'}}>
              Renvoyer l’e-mail de confirmation
            </Typography>
          </Button>
        </TabPanel>
      </Box>
      <ResetDialog
        activation
        lyen='send-email-confirmation'
        title='Envoi de l’e-mail de confirmation'
        content='Si vous n’avez pas reçu l’e-mail de confirmation, renseignez le champ et validez le formulaire.'
        open={openDialog}
        setOpen={setOpenDialog}
        setLoading={setLoading}
        setError={setError}
        setSuccess={setSuccess}
      />

      {loading && <LinearProgress size={24} style={{width: '100%'}} />}

      {error && (
        <Snackbar
          open={open}
          autoHideDuration={6000}
          onClose={handleClose}
        >
          <Alert severity='error' onClose={handleClose}><strong>{error}</strong></Alert>
        </Snackbar>
      )}

      {success && (
        <Snackbar
          open={success}
          autoHideDuration={15_000}
          onClose={handleClose}
        >
          <Alert severity='success' onClose={handleClose}><strong>Veuillez confirmer votre adresse e-mail via le lien qui vous a été envoyé.</strong></Alert>
        </Snackbar>
      )}
    </Container>
  )
}

Koneksyon.propTypes = {
  chimen: PropTypes.string.isRequired
}

export default Koneksyon
