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

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle
} from '@repo/ui/components/ui/card'
import { Button } from '@repo/ui/components/ui/button'
import { Kbd } from '@repo/ui/components/ui/kbd'
import {
  NativeSelect,
  NativeSelectOption
} from '@repo/ui/components/ui/native-select'
import { useOutletContext } from 'react-router'
import type { User } from '@repo/ui/routes/users/data'

import type { Email } from './data'
import { type Schema, formSchema } from './add'
import { Spinner } from '@repo/ui/components/ui/spinner'

export function Primary({ items = [] }: { items: Email[] }) {
  const emails = items.map((props) => {
    const [, email] = props.sk.split('#') as [string, string]
    return { ...props, email }
  }) as Email[]
  const primary = emails.find((e) => e.email_primary === true)
  const { revalidate } = useRevalidator()
  const { user } = useOutletContext() as { user: User }
  const { runAsync } = useRequest(
    async ({ email }) => {
      // Doesn't use `user` because the data could be outdated
      const selected = emails.find((e) => e.email === email)
      const new_email = selected?.email
      const old_email = primary?.email

      if (new_email === old_email) {
        return
      }

      const r = await fetch(`/api/users/${user.id}/emails/primary`, {
        method: 'PATCH',
        headers: new Headers({ 'Content-Type': 'application/json' }),
        body: JSON.stringify({
          new_email,
          old_email,
          email_verified: selected?.email_verified
        })
      })

      if (!r.ok) {
        throw await r.json()
      }
    },
    { manual: true }
  )

  const { handleSubmit, register, formState } = useForm({
    resolver: zodResolver(formSchema)
  })

  const onSubmit = async ({ email }: Schema) => {
    try {
      await runAsync({ email })
      toast.success(`O email principal foi alterado para: ${email}.`)
      revalidate()
    } catch {}
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-lg">Email principal</CardTitle>
        <CardDescription>
          <Kbd className="font-mono border">
            <span className="truncate max-lg:max-w-62">{primary?.email}</span>
          </Kbd>{' '}
          será usado para mensagens e pode ser usado para redefinições de senha.
        </CardDescription>
      </CardHeader>
      <CardContent>
        <form onSubmit={handleSubmit(onSubmit)}>
          <fieldset disabled={formState.isSubmitting} className="flex gap-1.5">
            <NativeSelect defaultValue={primary?.email} {...register('email')}>
              {emails.map(({ email }) => {
                return (
                  <NativeSelectOption key={email} value={email}>
                    {email}
                  </NativeSelectOption>
                )
              })}
            </NativeSelect>
            <Button
              type="submit"
              className="overflow-hidden cursor-pointer relative"
            >
              {formState.isSubmitting && (
                <div className="absolute inset-0 bg-lime-500 flex items-center justify-center">
                  <Spinner />
                </div>
              )}
              Alterar email
            </Button>
          </fieldset>
        </form>
      </CardContent>
    </Card>
  )
}
