import { useSearchParams, Link } from 'react-router'
import { useForm } from 'react-hook-form'
import { ErrorMessage } from '@hookform/error-message'
import { isValidCPF } from '@brazilian-utils/brazilian-utils'
import { yupResolver } from '@hookform/resolvers/yup'
import { Card } from '~/layouts/auth/layout'
import { Control, Label, Input, Button, Error } from '~/components/form'
import { Heading } from '~/components/heading'
import { useMutation } from '@tanstack/react-query'
import * as yup from 'yup'
import { encode, parse } from '../_base64state'
import axios from '~/axios'
import Password from './_password'

yup.addMethod(yup.string, 'username', function (message) {
  return this.test(
    'username',
    message,
    (x) => isValidCPF(x) || yup.string().email().isValid(x),
  )
})

export const schema = yup.object({
  username: yup
    .string()
    .trim()
    .lowercase()
    .username('Deve ser um Email ou CPF válido')
    .transform((x) => (isValidCPF(x) ? x.replace(/\D/g, '') : x))
    .required('Digite um Email ou CPF'),
})

export default function Component() {
  const [searchParams] = useSearchParams()
  const state = parse(searchParams.get('state'))

  if (state?.['cognito:sub']) {
    return <Password />
  }

  return <SignIn />
}

function SignIn() {
  const [searchParams, setSearchParams] = useSearchParams()
  const { handleSubmit, formState, setError, register } = useForm({
    resolver: yupResolver(schema),
  })

  const { mutateAsync } = useMutation({
    mutationFn: async ({ username }) => {
      const { data } = await axios.get(`/search/lookup/${username}`)
      return data
    },
    onSuccess: (data) => {
      setSearchParams((searchParams) => {
        searchParams.set('state', encode(data))
        return searchParams
      })
    },
  })

  const formError = (message) => {
    setError('username', {
      type: 'manual',
      message,
    })
  }

  const onSubmit = async ({ username }) => {
    try {
      await mutateAsync({ username })
    } catch ({ message }) {
      switch (message) {
        case 'User not found.':
          return formError(
            'Não encontramos sua conta. Por favor, verifique se seu Email ou CPF estão corretos.',
          )
        default:
          return formError(message)
      }
    }
  }

  return (
    <Card>
      <Heading>Digite o seu email ou cpf para continuar</Heading>

      {/* Sign in */}
      <form onSubmit={handleSubmit(onSubmit)} className="space-y-2.5">
        <Control
          className="space-y-0.5"
          aria-invalid={'username' in formState.errors}
        >
          <Label aria-required={true}>Email ou CPF</Label>
          <Input
            className="w-full"
            autoFocus={true}
            {...register('username')}
          />
          <ErrorMessage
            errors={formState.errors}
            name="username"
            render={({ message }) => <Error>{message}</Error>}
          />
        </Control>

        <Button
          type="submit"
          className="w-full"
          isLoading={formState.isSubmitting}
        >
          Continuar
        </Button>
      </form>

      <div className="flex justify-center items-center gap-4">
        <span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
        <span>ou</span>
        <span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
      </div>

      <Button
        as={Link}
        to={{
          pathname: './passcode',
          search: searchParams.toString(),
        }}
        relative="path"
        className="flex justify-center items-center !bg-yellow-primary w-full"
      >
        Entrar com código de acesso
      </Button>
    </Card>
  )
}
