import { useForm } from 'react-hook-form'
import { useRequest } from 'ahooks'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import { toast } from 'sonner'

import { Button } from '@repo/ui/components/ui/button'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormMessage
} from '@repo/ui/components/ui/form'
import { Input } from '@repo/ui/components/ui/input'
import { Spinner } from '@repo/ui/components/ui/spinner'
import { useOutletContext } from 'react-router'
import type { User } from '@repo/ui/routes/users/data'
import { useRevalidator } from 'react-router'

export const formSchema = z.object({
  email: z.email('Email inválido').trim().toLowerCase()
})

export type Schema = z.infer<typeof formSchema>

export function Add() {
  const { revalidate } = useRevalidator()
  const { user } = useOutletContext() as { user: User }
  const { runAsync } = useRequest(
    async (data) => {
      const r = await fetch(`/api/users/${user.id}/emails`, {
        method: 'POST',
        headers: new Headers({ 'Content-Type': 'application/json' }),
        body: JSON.stringify(data)
      })

      if (!r.ok) {
        throw await r.json()
      }
    },
    { manual: true }
  )
  const form = useForm({ resolver: zodResolver(formSchema) })
  const { handleSubmit, control, formState, reset } = form

  const onSubmit = async ({ email }: Schema) => {
    try {
      await runAsync({ email })

      reset()
      revalidate()
      toast.success(
        `Enviamos um email de verificação para ${email}. Por favor, siga as instruções que constam nele.`
      )
    } catch (err) {
      // @ts-ignore
      if (err?.type === 'EmailConflictError') {
        toast.error(`O endereço de email ${email} já está em uso.`)
      }
    }
  }

  return (
    <Form {...form}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <fieldset
          disabled={formState.isSubmitting}
          className="space-y-2.5 lg:w-2/3"
        >
          <h2 className="font-semibold">Adicionar email</h2>

          <div className="flex gap-2.5">
            <FormField
              control={control}
              name="email"
              defaultValue=""
              render={({ field }) => (
                <FormItem className="w-full">
                  <FormControl>
                    <Input placeholder="seu@email.com" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />

            <Button
              type="submit"
              className="relative overflow-hidden cursor-pointer"
            >
              {formState.isSubmitting && (
                <div className="absolute inset-0 bg-lime-500 flex items-center justify-center">
                  <Spinner />
                </div>
              )}
              Adicionar email
            </Button>
          </div>
        </fieldset>
      </form>
    </Form>
  )
}
