import { Button } from '@/components/ui/button';
import { OnboardingLayout } from '@/features/onboard/components/onboarding-layout';
import { OnboardingVerifyOtpStep } from '@/features/onboard/components/onboarding-verify-otp-step';
import {
  OTP_MAX_ATTEMPTS,
  getOnboardingSessionState,
  updateOnboardingSessionState,
} from '@/features/onboard/onboarding-session';
import type { VerifyOtpValues } from '@/features/onboard/onboarding.types';
import { apiClient } from '@/lib/api-client';
import { zodResolver } from '@hookform/resolvers/zod';
import { onboardingVerifyOtpSchema } from '@repo/api-contract';
import { useNavigate } from '@tanstack/react-router';
import { useEffect, useMemo, useState } from 'react';
import { useForm, useWatch } from 'react-hook-form';

export function OnboardVerifyPage() {
  const navigate = useNavigate();
  const initialState = useMemo(() => getOnboardingSessionState(), []);
  const [requestId] = useState<string | null>(initialState.requestId);
  const [onboardingEmail, setOnboardingEmail] = useState<string | null>(
    initialState.onboardingEmail
  );
  const [remainingAttempts, setRemainingAttempts] = useState<number>(
    initialState.remainingAttempts || OTP_MAX_ATTEMPTS
  );
  const [resendCooldownSeconds, setResendCooldownSeconds] = useState<number>(
    initialState.resendCooldownSeconds || 0
  );
  const [isResending, setIsResending] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [infoMessage, setInfoMessage] = useState<string | null>(null);

  const form = useForm<VerifyOtpValues>({
    resolver: zodResolver(onboardingVerifyOtpSchema.omit({ requestId: true })),
    mode: 'onChange',
    defaultValues: initialState.verifyOtpForm,
  });
  const values = useWatch({ control: form.control });

  useEffect(() => {
    if (requestId && onboardingEmail) return;
    void navigate({ to: '/onboard' });
  }, [navigate, onboardingEmail, requestId]);

  useEffect(() => {
    updateOnboardingSessionState((current) => ({
      ...current,
      onboardingEmail,
      remainingAttempts,
      resendCooldownSeconds,
      verifyOtpForm: {
        otp: values.otp ?? '',
      },
    }));
  }, [onboardingEmail, remainingAttempts, resendCooldownSeconds, values.otp]);

  useEffect(() => {
    if (resendCooldownSeconds <= 0) return;

    const timeout = window.setTimeout(() => {
      setResendCooldownSeconds((current) => Math.max(0, current - 1));
    }, 1000);

    return () => {
      window.clearTimeout(timeout);
    };
  }, [resendCooldownSeconds]);

  const onSubmit = async (payload: VerifyOtpValues) => {
    if (!requestId) {
      setErrorMessage('No encontramos una solicitud de onboarding activa.');
      return;
    }

    setErrorMessage(null);

    try {
      const result = await apiClient.onboarding.verifyOtp({
        requestId,
        otp: payload.otp,
      });

      setRemainingAttempts(result.remainingAttempts);
      setResendCooldownSeconds(result.cooldownSeconds);
      setInfoMessage(result.message);

      updateOnboardingSessionState((current) => ({
        ...current,
        remainingAttempts: result.remainingAttempts,
        resendCooldownSeconds: result.cooldownSeconds,
      }));

      if (result.verified) {
        const nextVerifiedEmail = result.email ?? onboardingEmail;

        updateOnboardingSessionState((current) => ({
          ...current,
          verifiedEmail: nextVerifiedEmail,
          remainingAttempts: result.remainingAttempts,
          resendCooldownSeconds: result.cooldownSeconds,
        }));

        await navigate({ to: '/onboard/complete' });
      }
    } catch {
      setErrorMessage('No pudimos verificar el OTP. Intenta nuevamente.');
    }
  };

  const onResend = async () => {
    if (!requestId) {
      setErrorMessage('No encontramos una solicitud de onboarding activa.');
      return;
    }

    setIsResending(true);
    setErrorMessage(null);

    try {
      const result = await apiClient.onboarding.resendOtp({ requestId });
      setOnboardingEmail(result.email);
      setRemainingAttempts(result.remainingAttempts);
      setResendCooldownSeconds(result.cooldownSeconds);
      form.reset({ otp: '' });
      setInfoMessage(result.message);

      updateOnboardingSessionState((current) => ({
        ...current,
        onboardingEmail: result.email,
        remainingAttempts: result.remainingAttempts,
        resendCooldownSeconds: result.cooldownSeconds,
        verifyOtpForm: { otp: '' },
      }));
    } catch {
      setErrorMessage('No pudimos reenviar el OTP. Intenta nuevamente.');
    } finally {
      setIsResending(false);
    }
  };

  return (
    <OnboardingLayout
      title="Verifica tu email"
      description="Ingresa el OTP para validar tu cuenta."
    >
      <OnboardingVerifyOtpStep
        form={form}
        email={onboardingEmail}
        errorMessage={errorMessage}
        infoMessage={infoMessage}
        remainingAttempts={remainingAttempts}
        resendCooldownSeconds={resendCooldownSeconds}
        isResending={isResending}
        onSubmit={onSubmit}
        onResend={onResend}
      />
      <Button
        variant="ghost"
        className="mt-2 w-full"
        onClick={() => {
          void navigate({ to: '/onboard' });
        }}
      >
        Volver al paso anterior
      </Button>
    </OnboardingLayout>
  );
}
