import { zodResolver } from '@hookform/resolvers/zod';
import { Eye, EyeOff, Lock } from 'lucide-react';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Link, useSearchParams } from 'react-router-dom';
import { z } from 'zod';

import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useRsaPublicKey } from '@/hooks/auth/useRsaPublicKey';
import { useVerifyPasswordReset } from '@/hooks/auth/useVerifyPasswordReset';
import { encryptRsaOaep } from '@/lib/rsa';
import { cn } from '@/lib/utils';

const resetPasswordSchema = z
  .object({
    password: z
      .string()
      .min(8, 'Password must be at least 8 characters')
      .max(128, 'Password must be at most 128 characters'),
    confirmPassword: z.string(),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
    path: ['confirmPassword'],
  });

type ResetPasswordForm = z.infer<typeof resetPasswordSchema>;

export function ResetPasswordPage() {
  const [searchParams] = useSearchParams();
  const token = searchParams.get('token') ?? '';

  const [showPassword, setShowPassword] = useState(false);
  const [showConfirmPassword, setShowConfirmPassword] = useState(false);

  const rsaQuery = useRsaPublicKey();
  const resetMutation = useVerifyPasswordReset();

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<ResetPasswordForm>({
    resolver: zodResolver(resetPasswordSchema),
  });

  const rsaKey = rsaQuery.data?.public_key;

  const onSubmit = async (data: ResetPasswordForm) => {
    if (!rsaKey || !token) return;

    try {
      const encryptedPassword = await encryptRsaOaep(data.password, rsaKey);
      await resetMutation.mutateAsync({
        token,
        password: encryptedPassword,
      });
    } catch {
      // error handled via mutation state
    }
  };

  if (!token) {
    return (
      <>
        <div className="mb-8">
          <h1 className="text-[24px] font-semibold tracking-tight text-foreground">
            Invalid reset link
          </h1>
          <p className="mt-1.5 text-[14px] text-muted-foreground">
            This password reset link is invalid or has expired. Please request a new one.
          </p>
        </div>
        <Link
          to="/auth/forgot-password"
          className="text-[14px] font-medium text-foreground transition-colors hover:text-primary"
        >
          Request a new reset link
        </Link>
      </>
    );
  }

  return (
    <>
      <div className="mb-8">
        <h1 className="text-[24px] font-semibold tracking-tight text-foreground">
          Set new password
        </h1>
        <p className="mt-1.5 text-[14px] text-muted-foreground">
          Enter your new password below to reset your account.
        </p>
      </div>

      <form onSubmit={handleSubmit(onSubmit)} className="space-y-5">
        <div className="space-y-2">
          <Label htmlFor="password">New Password</Label>
          <div className="relative">
            <Lock className="pointer-events-none absolute left-3 top-1/2 size-[18px] -translate-y-1/2 text-muted-foreground" />
            <Input
              id="password"
              type={showPassword ? 'text' : 'password'}
              {...register('password')}
              placeholder="At least 8 characters"
              autoComplete="new-password"
              className="h-11 pl-11 pr-11 text-[15px]"
            />
            <button
              type="button"
              onClick={() => setShowPassword(!showPassword)}
              className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground"
              tabIndex={-1}
              aria-label={showPassword ? 'Hide password' : 'Show password'}
            >
              {showPassword ? <EyeOff className="size-[18px]" /> : <Eye className="size-[18px]" />}
            </button>
          </div>
          {errors.password && (
            <p className="text-[13px] text-destructive">{errors.password.message}</p>
          )}
        </div>

        <div className="space-y-2">
          <Label htmlFor="confirmPassword">Confirm New Password</Label>
          <div className="relative">
            <Lock className="pointer-events-none absolute left-3 top-1/2 size-[18px] -translate-y-1/2 text-muted-foreground" />
            <Input
              id="confirmPassword"
              type={showConfirmPassword ? 'text' : 'password'}
              {...register('confirmPassword')}
              placeholder="Confirm your new password"
              autoComplete="new-password"
              className="h-11 pl-11 pr-11 text-[15px]"
            />
            <button
              type="button"
              onClick={() => setShowConfirmPassword(!showConfirmPassword)}
              className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground"
              tabIndex={-1}
              aria-label={showConfirmPassword ? 'Hide password' : 'Show password'}
            >
              {showConfirmPassword ? (
                <EyeOff className="size-[18px]" />
              ) : (
                <Eye className="size-[18px]" />
              )}
            </button>
          </div>
          {errors.confirmPassword && (
            <p className="text-[13px] text-destructive">{errors.confirmPassword.message}</p>
          )}
        </div>

        {resetMutation.isError && (
          <div className="rounded-lg bg-destructive/8 px-3.5 py-3 text-[13px] text-destructive">
            {resetMutation.error instanceof Error
              ? resetMutation.error.message
              : 'An error occurred. Please try again.'}
          </div>
        )}

        <button
          type="submit"
          disabled={resetMutation.isPending}
          className={cn(
            'flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-primary text-[15px] font-medium text-primary-foreground',
            'transition-all hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40',
            'disabled:pointer-events-none disabled:opacity-50',
          )}
        >
          {resetMutation.isPending ? (
            <>
              <svg
                className="size-[18px] animate-spin"
                viewBox="0 0 24 24"
                fill="none"
                role="status"
                aria-label="Loading"
              >
                <title>Loading</title>
                <circle
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  strokeWidth="3"
                  className="opacity-25"
                />
                <path
                  d="M12 2a10 10 0 0 1 10 10"
                  stroke="currentColor"
                  strokeWidth="3"
                  strokeLinecap="round"
                  className="opacity-75"
                />
              </svg>
              Resetting...
            </>
          ) : (
            'Reset password'
          )}
        </button>
      </form>
    </>
  );
}
