'use client'

import React, { useState } from 'react'
import * as yup from 'yup'
import { Controller, useForm } from 'react-hook-form'
import { AxiosError } from 'axios'
import Link from 'next/link'
import { useRouter, useSearchParams } from 'next/navigation'
import { yupResolver } from '@hookform/resolvers/yup'
import {
  Button,
  HelperText,
  Label,
  TextInput,
  Checkbox,
  Alert,
} from 'flowbite-react'

import formTheme from '@/lib/themes/form'
import buttonTheme from '@/lib/themes/button'
import { useAuth } from '@/lib/context/AuthContext'
import { HttpStatusCode } from '@/lib/types/enums/HttpStatusCode'

const formSchema = yup.object({
  username: yup
    .string()
    .email('Invalid email address')
    .required('Email is required'),
  password: yup.string().required('Password is required'),
  remember: yup.boolean().default(false),
})

export default function Form() {
  const router = useRouter()
  const [processing, setProcessing] = useState(false)
  const searchParams = useSearchParams()
  const { login } = useAuth()

  const {
    register,
    handleSubmit,
    control,
    formState: { errors },
    setError,
  } = useForm({
    resolver: yupResolver(formSchema),
    defaultValues: {
      username: '',
      password: '',
      remember: false,
    },
  })

  async function handleLogin(data: yup.InferType<typeof formSchema>) {
    try {
      setProcessing(true)

      await login(data)

      if (searchParams.get('redirect')) {
        return router.push(searchParams.get('redirect') as string)
      }

      return router.push('/')
    } catch (e) {
      if (e instanceof AxiosError && e.response) {
        const {
          errors,
        }: {
          errors: Record<keyof yup.InferType<typeof formSchema>, string[]>
        } = e.response.data

        Object.entries(errors ?? []).forEach(([key, message]) => {
          setError(key as keyof yup.InferType<typeof formSchema>, {
            type: 'manual',
            message: message[0],
          })
        })

        if (e.status === HttpStatusCode.CRSF_TOKEN_MISMATCH) {
          setError('root', {
            message: 'Please logout on other sessions before logging in.',
          })
        }

        return
      }

      setError('root', {
        message: 'Oops! Something went wrong. Please try again later.',
      })
    } finally {
      setProcessing(false)
    }
  }

  return (
    <form onSubmit={handleSubmit(handleLogin)}>
      <div>
        <h1 className="text-3xl font-semibold text-slate-800 mb-3 text-center">
          Sign In
        </h1>
      </div>

      {errors.root?.message && (
        <Alert
          color="failure"
          className="mt-4"
          onDismiss={() => {
            setError('root', { message: '' })
          }}
        >
          {errors.root?.message}
        </Alert>
      )}

      <div className="space-y-5 mt-10">
        {/* Email Address */}
        <div>
          <div className="mb-2 block text-left">
            <Label htmlFor="username" theme={formTheme.label}>
              Email Address
            </Label>
          </div>
          <TextInput
            id="username"
            type="email"
            placeholder="Enter your email address..."
            theme={formTheme.textInput}
            {...register('username')}
          />
          <HelperText color="failure">{errors.username?.message}</HelperText>
        </div>

        {/* Password */}
        <div className="mt-4 text-left">
          <div className="mb-2 flex justify-between items-center">
            <Label htmlFor="password" theme={formTheme.label}>
              Password
            </Label>

            <Link
              href="/forgot-password"
              className="text-primary text-sm hover:underline font-medium"
            >
              Forgot Password
            </Link>
          </div>
          <TextInput
            id="password"
            type="password"
            placeholder="********"
            theme={formTheme.textInput}
            {...register('password')}
          />
          <HelperText color="failure">{errors.password?.message}</HelperText>
        </div>

        {/* Remember Me */}
        <div className="mt-4">
          <div className="flex items-center gap-2">
            <Controller
              name="remember"
              control={control}
              render={({ field }) => (
                <Checkbox
                  id="remember"
                  color="blue"
                  checked={field.value}
                  onChange={field.onChange}
                />
              )}
            />
            <Label htmlFor="remember" className="flex">
              Remember Me
            </Label>
          </div>
        </div>
      </div>

      <div className="mt-8">
        <Button
          type="submit"
          theme={buttonTheme.button}
          className="mt-6 w-full"
          disabled={processing}
        >
          Login
        </Button>
      </div>
    </form>
  )
}
