'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useAuthActions } from '@convex-dev/auth/react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';

import { PASSWORD_MAX, PASSWORD_MIN } from '@gib/backend/types';
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Input,
  InputOTP,
  InputOTPGroup,
  InputOTPSeparator,
  InputOTPSlot,
  SubmitButton,
} from '@gib/ui';

const forgotPasswordSchema = z.object({
  email: z.email({ message: 'Invalid email.' }),
});

const resetVerificationSchema = z
  .object({
    code: z.string({ message: 'Invalid code.' }),
    newPassword: z
      .string()
      .min(PASSWORD_MIN, {
        message: `Password must be at least ${PASSWORD_MIN} characters.`,
      })
      .max(PASSWORD_MAX, {
        message: `Password must be no more than ${PASSWORD_MAX} characters.`,
      })
      .regex(/^\S+$/, {
        message: 'Password must not contain whitespace.',
      })
      .regex(/[0-9]/, {
        message: 'Password must contain at least one digit.',
      })
      .regex(/[a-z]/, {
        message: 'Password must contain at least one lowercase letter.',
      })
      .regex(/[A-Z]/, {
        message: 'Password must contain at least one uppercase letter.',
      })
      .regex(/[\p{P}\p{S}]/u, {
        message: 'Password must contain at least one symbol.',
      }),
    confirmPassword: z.string().min(PASSWORD_MIN, {
      message: `Password must be at least ${PASSWORD_MIN} characters.`,
    }),
  })
  .refine((data) => data.newPassword === data.confirmPassword, {
    message: 'Passwords do not match!',
    path: ['confirmPassword'],
  });

const ForgotPassword = () => {
  const { signIn } = useAuthActions();
  const [flow, setFlow] = useState<'reset' | 'reset-verification'>('reset');
  const [email, setEmail] = useState<string>('');
  const [loading, setLoading] = useState(false);
  const [code, setCode] = useState<string>('');
  const router = useRouter();

  const forgotPasswordForm = useForm<z.infer<typeof forgotPasswordSchema>>({
    resolver: zodResolver(forgotPasswordSchema),
    defaultValues: { email },
  });

  const resetVerificationForm = useForm<
    z.infer<typeof resetVerificationSchema>
  >({
    resolver: zodResolver(resetVerificationSchema),
    defaultValues: { code, newPassword: '', confirmPassword: '' },
  });

  const handleForgotPasswordSubmit = async (
    values: z.infer<typeof forgotPasswordSchema>,
  ) => {
    const formData = new FormData();
    formData.append('email', values.email);
    formData.append('flow', flow);
    setLoading(true);
    try {
      await signIn('password', formData).then(() => {
        setEmail(values.email);
        setFlow('reset-verification');
      });
    } catch (error) {
      console.error('Error resetting password: ', error);
      toast.error('Error resetting password.');
    } finally {
      forgotPasswordForm.reset();
      setLoading(false);
    }
  };

  const handleResetVerificationSubmit = async (
    values: z.infer<typeof resetVerificationSchema>,
  ) => {
    const formData = new FormData();
    formData.append('code', code);
    formData.append('newPassword', values.newPassword);
    formData.append('email', email);
    formData.append('flow', flow);
    setLoading(true);
    try {
      await signIn('password', formData);
      router.push('/');
    } catch (error) {
      console.error('Error resetting password: ', error);
      toast.error('Error resetting password.');
    } finally {
      resetVerificationForm.reset();
      setLoading(false);
    }
  };

  return (
    <div className='flex flex-col items-center'>
      <Card className='bg-card/25 min-h-[400px] w-sm p-4 lg:w-md'>
        <CardHeader className='flex flex-col items-center gap-4'>
          {flow === 'reset' ? (
            <>
              <CardTitle className='text-2xl font-bold'>
                Forgot Password
              </CardTitle>
              <CardDescription>
                Enter your email address and we will send you a link to reset
                your password.
              </CardDescription>
            </>
          ) : (
            <>
              <CardTitle className='text-2xl font-bold'>
                Reset Password
              </CardTitle>
              <CardDescription>
                Enter your code and new password and we will reset your
                password.
              </CardDescription>
            </>
          )}
        </CardHeader>
        <CardContent>
          <Card className='bg-card/50'>
            <CardContent>
              {flow === 'reset' ? (
                <Form {...forgotPasswordForm}>
                  <form
                    onSubmit={forgotPasswordForm.handleSubmit(
                      handleForgotPasswordSubmit,
                    )}
                    className='flex flex-col space-y-4'
                  >
                    <FormField
                      control={forgotPasswordForm.control}
                      name='email'
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel className='text-xl'>Email</FormLabel>
                          <FormControl>
                            <Input
                              type='email'
                              placeholder='you@example.com'
                              {...field}
                            />
                          </FormControl>
                          <div className='flex w-full flex-col items-center'>
                            <FormMessage className='w-5/6 text-center' />
                          </div>
                        </FormItem>
                      )}
                    />
                    <SubmitButton
                      disabled={loading}
                      pendingText='Sending Email...'
                      className='mx-auto w-2/3 text-xl font-semibold'
                    >
                      Send Email
                    </SubmitButton>
                  </form>
                </Form>
              ) : (
                <Form {...resetVerificationForm}>
                  <form
                    onSubmit={resetVerificationForm.handleSubmit(
                      handleResetVerificationSubmit,
                    )}
                    className='flex flex-col space-y-4'
                  >
                    <FormField
                      control={resetVerificationForm.control}
                      name='code'
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel className='text-xl'>Code</FormLabel>
                          <FormControl>
                            <InputOTP
                              maxLength={6}
                              {...field}
                              value={code}
                              onChange={(value) => setCode(value)}
                            >
                              <InputOTPGroup>
                                <InputOTPSlot index={0} />
                                <InputOTPSlot index={1} />
                                <InputOTPSlot index={2} />
                                <InputOTPSeparator />
                                <InputOTPSlot index={3} />
                                <InputOTPSlot index={4} />
                                <InputOTPSlot index={5} />
                              </InputOTPGroup>
                            </InputOTP>
                          </FormControl>
                          <FormDescription>
                            Please enter the one-time password sent to your
                            phone.
                          </FormDescription>
                          <div className='flex w-full flex-col items-center'>
                            <FormMessage className='w-5/6 text-center' />
                          </div>
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={resetVerificationForm.control}
                      name='newPassword'
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel className='text-xl'>
                            New Password
                          </FormLabel>
                          <FormControl>
                            <Input
                              type='password'
                              placeholder='Your password'
                              {...field}
                            />
                          </FormControl>
                          <div className='flex w-full flex-col items-center'>
                            <FormMessage className='w-5/6 text-center' />
                          </div>
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={resetVerificationForm.control}
                      name='confirmPassword'
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel className='text-xl'>
                            Confirm Passsword
                          </FormLabel>
                          <FormControl>
                            <Input
                              type='password'
                              placeholder='Confirm your password'
                              {...field}
                            />
                          </FormControl>
                          <div className='flex w-full flex-col items-center'>
                            <FormMessage className='w-5/6 text-center' />
                          </div>
                        </FormItem>
                      )}
                    />
                    <SubmitButton
                      disabled={loading}
                      pendingText='Resetting Password...'
                      className='mx-auto w-2/3 text-xl font-semibold'
                    >
                      Reset Password
                    </SubmitButton>
                  </form>
                </Form>
              )}
            </CardContent>
          </Card>
        </CardContent>
      </Card>
    </div>
  );
};
export default ForgotPassword;
