import { useRouter } from 'next/router'
import Link from 'next/link'
import useTranslation from 'next-translate/useTranslation'
import { useTheme } from 'next-themes'
import axios from 'axios'

import { SocialMediaButton } from '../design/SocialMediaButton'
import { Main } from '../design/Main'
import { Input } from '../design/Input'
import { Button } from '../design/Button'
import { FormState } from '../design/FormState'
import { AuthenticationForm } from './'
import { userSchema } from '../../models/User'
import { api } from 'utils/api'
import {
  Tokens,
  Authentication as AuthenticationClass
} from '../../utils/authentication'
import { useForm, HandleSubmitCallback } from '../../hooks/useForm'

export interface AuthenticationProps {
  mode: 'signup' | 'signin'
}

export const Authentication: React.FC<AuthenticationProps> = (props) => {
  const { mode } = props

  const router = useRouter()
  const { lang, t } = useTranslation()
  const { theme } = useTheme()

  const { errors, fetchState, message, getErrorTranslation, handleSubmit } =
    useForm({
      validateSchemaObject: {
        ...(mode === 'signup' && { name: userSchema.name }),
        email: userSchema.email,
        password: userSchema.password
      }
    })

  const onSubmit: HandleSubmitCallback = async (formData) => {
    if (mode === 'signup') {
      try {
        await api.post(
          `/users/signup?redirectURI=${window.location.origin}/authentication/signin`,
          { ...formData, language: lang, theme }
        )
        return {
          type: 'success',
          value: 'authentication:success-signup'
        }
      } catch (error) {
        if (axios.isAxiosError(error) && error.response?.status === 400) {
          return {
            type: 'error',
            value: 'authentication:alreadyUsed'
          }
        }
        return {
          type: 'error',
          value: 'errors:server-error'
        }
      }
    } else {
      try {
        const { data } = await api.post<Tokens>('/users/signin', formData)
        const authentication = new AuthenticationClass(data)
        authentication.signin()
        await router.push('/application')
        return null
      } catch (error) {
        if (axios.isAxiosError(error) && error.response?.status === 400) {
          return {
            type: 'error',
            value: 'authentication:wrong-credentials'
          }
        }
        return {
          type: 'error',
          value: 'errors:server-error'
        }
      }
    }
  }

  return (
    <Main>
      <section className='flex flex-col sm:items-center sm:w-full'>
        <div className='flex flex-col items-center justify-center space-y-6 sm:w-4/6 sm:flex-row sm:space-x-6 sm:space-y-0'>
          <SocialMediaButton socialMedia='Google' />
          <SocialMediaButton socialMedia='GitHub' />
          <SocialMediaButton socialMedia='Discord' />
        </div>
      </section>
      <section className='text-center text-lg font-paragraph pt-8'>
        {t('authentication:or')}
      </section>
      <AuthenticationForm onSubmit={handleSubmit(onSubmit)}>
        {mode === 'signup' && (
          <Input
            type='text'
            placeholder={t('common:name')}
            name='name'
            label={t('common:name')}
            error={getErrorTranslation(errors.name)}
          />
        )}
        <Input
          type='email'
          placeholder='Email'
          name='email'
          label='Email'
          error={getErrorTranslation(errors.email)}
        />
        <Input
          type='password'
          placeholder={t('authentication:password')}
          name='password'
          label={t('authentication:password')}
          showForgotPassword={mode === 'signin'}
          error={getErrorTranslation(errors.password)}
        />
        <Button data-cy='submit' className='w-full mt-6' type='submit'>
          {t('authentication:submit')}
        </Button>
        <p className='mt-3 font-headline text-sm text-green-800 dark:text-green-400 hover:underline'>
          <Link
            href={
              mode === 'signup'
                ? '/authentication/signin'
                : '/authentication/signup'
            }
          >
            <a>
              {mode === 'signup'
                ? t('authentication:already-have-an-account')
                : t('authentication:dont-have-an-account')}
            </a>
          </Link>
        </p>
      </AuthenticationForm>
      <FormState id='message' state={fetchState} message={message} />
    </Main>
  )
}
