import { Card, CardContent, CardHeader, CardFooter } from '@/components/ui/card';
import { ResetPasswordSchema } from '@/data/form';
import { Field, FieldError, FieldLabel } from '@/components/ui/field';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { zodResolver } from '@hookform/resolvers/zod';
import { useState, useCallback } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { PageRouting } from '@/const/PageRouting';
import { Stepper, StepperContent, StepperIndicator, StepperItem, StepperNav, StepperPanel, StepperSeparator, StepperTrigger } from '@/components/ui/stepper';
import * as z from 'zod';
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp';
import { Validator } from '@/util/Validator';
import { Eye, EyeOff, LoaderCircleIcon, CircleCheckBigIcon } from 'lucide-react';
import { AccountNetwork } from '@/network/AccountNetwork';
import { Label } from '@/components/ui/label';

const steps = [1, 2, 3, 4];

export default function ResetPasswordPage() {
  const [currentStep, setCurrentStep] = useState(1);
  const [showPassword, setShowPassword] = useState(false);
  const [showPasswordConfirm, setShowPasswordConfirm] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const navigate = useNavigate();
  const accountNetwork = new AccountNetwork();

  const resetPasswordForm = useForm<z.infer<typeof ResetPasswordSchema>>({
    resolver: zodResolver(ResetPasswordSchema),
    defaultValues: {
      email: "",
      code: "",
      password: "",
      passwordConfirm: ""
    }
  });
  
  const { email, code, password, passwordConfirm } = resetPasswordForm.watch();

  const moveToLoginPage = useCallback(() => {
    navigate(PageRouting["LOGIN"].path);
  }, []);

  const handleClickFirstStepButton = async () => {
    if (isLoading) return;
    if (!email || email.trim().length === 0) {
      resetPasswordForm.setError('email', {
        type: 'manual',
        message: '이메일을 입력해주십시오'
      });
      return;
    }
    const isEmailValid = await resetPasswordForm.trigger('email');
    if (!isEmailValid) {
      resetPasswordForm.setError('email', {
        type: 'validate',
        message: '이메일 형식이 올바르지 않습니다'
      });
      return;
    }

    setIsLoading(true);

    try {

      const response = await accountNetwork.sendResetPasswordCode({ email: email });
      const resData = response.data;
      
      if (!resData.success) {
        resetPasswordForm.setError('email', {
          message: '서버 오류로 코드 발송에 실패하였습니다. 잠시 후 다시 시도해주십시오.'
        });
        return;
      }

      setCurrentStep(current => current + 1);

    } catch (err) {
      resetPasswordForm.setError('email', {
        message: '서버 오류로 코드 발송에 실패하였습니다. 잠시 후 다시 시도해주십시오.'
      });
    } finally {
      setIsLoading(false);
    }
  }

  const handleSecondStepOTPCompleted = async () => {
    if (isLoading) return;
    const codeValid = await resetPasswordForm.trigger('code');
    if (!codeValid) {
      return;
    }

    const data = {
      email: email,
      code: code
    }

    setIsLoading(true);

    try {
      const response = await accountNetwork.verifyResetPasswordCode(data);
      const resData = response.data;
      console.log(resData);
      if (!resData.success || !resData.verified) {
        resetPasswordForm.setError('code', {
          type: 'value',
          message: resData.error
        });
        return;
      }

      setCurrentStep(current => current + 1);
    } catch (err) {
      resetPasswordForm.setError('code', {
        type: 'value',
        message: '서버 오류로 코드 인증에 실패하였습니다. 잠시 후 다시 시도해주십시오.'
      });
    } finally {
      setIsLoading(false);
    }
  }

  const handleThirdStepButton = async () => {
    if (isLoading) return;
    const passwordValid = await resetPasswordForm.trigger('password');
    if (!passwordValid) return;

    const passwordConfirmValid = await resetPasswordForm.trigger('passwordConfirm');
    if (!passwordConfirmValid) return;

    const data = {
      email: email,
      password: password
    }

    setIsLoading(true);

    try {
      const response = await accountNetwork.resetPassword(data);
      const resData = response.data;

      if (!resData.success) {
        resetPasswordForm.setError('password', {
          message: '서버 오류로 비밀번호 변경에 실패하였습니다. 잠시 후 다시 시도해주십시오.'
        });
        return;
      }

      setCurrentStep(current => current + 1);
    } catch (err) {
      resetPasswordForm.setError('password', {
        message: '서버 오류로 비밀번호 변경에 실패하였습니다. 잠시 후 다시 시도해주십시오.'
      });
    } finally {
      setIsLoading(false);
    }

  }

  return (
    <Stepper 
      value={currentStep}
      onValueChange={setCurrentStep}
      className="w-full h-full flex flex-col justify-center items-center"
      indicators={{
        loading: <LoaderCircleIcon className="size-3.5 animate-spin" />
      }}
    >
      <Card className="w-md pl-2 pr-2">
        <CardHeader>
          비밀번호 초기화
        </CardHeader>
        <CardContent>
          <StepperNav className="select-none">
            {steps.map((step) => (
              <StepperItem key={step} step={step} loading={isLoading}>
                <StepperTrigger asChild>
                  <StepperIndicator
                    className={[
                      `transition-all duration-300`,
                      `bg-accent text-accent-foreground rounded-full text-xs data-[state=completed]:bg-indigo-500 data-[state=completed]:text-primary-foreground data-[state=active]:bg-indigo-300 data-[state=active]:text-primary-foreground`,
                    ].join(' ')}
                  >
                    {step}
                  </StepperIndicator>
                </StepperTrigger>
                {
                steps.length > step 
                && <StepperSeparator
                  className="transition-all duration-300 group-data-[state=completed]/step:bg-indigo-500"
                  /> 
                } 
              </StepperItem>
            ))}
          </StepperNav>
        </CardContent>
        <CardContent>
          <StepperPanel>
            <StepperContent value={1} key={1}>
              <Field data-invalid={resetPasswordForm.formState.errors.email?.message ? true : false}>
                <FieldLabel htmlFor="reseet-password-email">이메일</FieldLabel>
                  <Controller
                    name="email"
                    control={resetPasswordForm.control}
                    render={({ field, fieldState }) => (
                      <>
                        <Input
                          {...field}
                          type="email"
                          id="reset-password-email"
                          aria-invalid={fieldState.invalid}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') {
                              e.preventDefault();
                              if (email.length === 0) return;
                              handleClickFirstStepButton();
                            }
                          }}
                        />
                        <FieldError className="font-[12px]" errors={[fieldState.error]} />
                      </>
                    )}
                  />
                </Field>
            </StepperContent>
            <StepperContent value={2} key={2}>
              <Controller 
                name="code"
                control={resetPasswordForm.control}
                render={
                  ({ field, fieldState }) => (
                    <div className="w-full flex flex-col justify-center gap-5">
                      <FieldLabel htmlFor="reset-password-code">코드 입력</FieldLabel>
                      <div className="flex flex-row justify-center items-center">
                        <InputOTP 
                          maxLength={8}
                          inputMode="text"
                          id="reset-password-code"
                          onComplete={handleSecondStepOTPCompleted}
                          value={field.value}
                          onChange={(value) => field.onChange(value)}
                          onBlur={field.onBlur}
                          required
                        >
                          <InputOTPGroup
                            className="gap-2.5 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border"
                          >
                            {
                              [0, 1, 2, 3, 4, 5, 6, 7].map((idx) => (
                                <InputOTPSlot index={idx} />
                              ))
                            }
                          </InputOTPGroup>
                        </InputOTP>
                      </div>
                      <FieldError errors={[fieldState.error]} />
                    </div>
                  )
                }
              />
            </StepperContent>
            <StepperContent value={3} key={3}>
              <div className="w-full flex flex-col gap-5 items-start">
                <FieldLabel htmlFor="reset-password-password">새 비밀번호</FieldLabel>
                <Controller
                  name="password"
                  control={resetPasswordForm.control}
                  render={({ field, fieldState }) => (
                    <>
                      <div className="relative w-full">
                        <Input
                          {...field}
                          type={ showPassword ? "text" : "password" }
                          id="reset-password-password"
                          aria-invalid={fieldState.invalid}
                          className="pr-10"
                        />
                        <button
                          type="button"
                          className="absolute top-1/2 right-2 -translate-y-1/2"
                          onClick={() => setShowPassword(prev => !prev)}
                        >
                          {
                            showPassword
                            ? <EyeOff size={14} />
                            : <Eye size={14} />
                          }
                        </button>
                      </div>
                      <FieldError className="text-[12px]" errors={[fieldState.error]} />
                    </>
                  )}
                />
                <FieldLabel htmlFor="reset-password-password-confirm">새 비밀번호 확인</FieldLabel>
                <Controller
                  name="passwordConfirm"
                  control={resetPasswordForm.control}
                  render={({ field, fieldState}) => (
                    <>
                      <div className="w-full relative">
                        <Input
                          {...field}
                          type={ showPasswordConfirm ? "text" : "password" }
                          id="reset-password-password-confirm"
                          className="pr-10"
                          aria-invalid={fieldState.invalid}
                        />
                        <button
                          type="button"
                          className="absolute top-1/2 right-2 -translate-y-1/2"
                          onClick={() => setShowPasswordConfirm(prev => !prev)}
                        >
                          {
                            showPasswordConfirm
                            ? <EyeOff size={14} />
                            : <Eye size={14} />
                          }
                        </button>
                      </div>
                      <FieldError className="text-[12px]" errors={[fieldState.error]} />
                    </>
                  )}
                />
              </div>
            </StepperContent>
            <StepperContent value={4} key={4}>
              <div className="w-full flex flex-col justify-center items-center gap-5">
                <CircleCheckBigIcon size={50} className="text-indigo-500" />
                <Label className="font-extrabold text-xl">비밀번호 변경 완료</Label>
              </div>
            </StepperContent>
          </StepperPanel>
        </CardContent>
        <CardFooter
          className="w-full"
        >
          <StepperPanel className="w-full">
            <StepperContent value={1}>
              <div className="w-full flex flex-row items-center gap-5">
                <Button 
                  className="flex-8 bg-indigo-500 hover:bg-indigo-400"
                  type="button"
                  form="form-reset-password"
                  disabled={
                    (email.trim().length < 1)
                  }
                  onClick={handleClickFirstStepButton}
                >
                  인증 번호 발송
                </Button>
                <Button
                  type="button"
                  className="flex-1 bg-stone-300 text-white hover:bg-stone-400"
                  onClick={moveToLoginPage}
                >
                  취소
                </Button>
              </div>
            </StepperContent>
            <StepperContent value={2} key={2}>
              <div className="w-full flex flex-row justify-end items-center gap-5">
                <Button
                  type="button"
                  className="bg-stone-300 text-white hover:bg-stone-400"
                  onClick={moveToLoginPage}
                >
                  취소
                </Button>
              </div>
            </StepperContent>
            <StepperContent value={3} key={3}>
              <div className="w-full flex flex-row align-center gap-5">
                <Button 
                  className="flex-8 bg-indigo-500 hover:bg-indigo-400"
                  type="button"
                  form="form-reset-password"
                  disabled={
                    (password.trim().length < 1)
                    && (passwordConfirm.trim().length < 1)
                  }
                  onClick={handleThirdStepButton}
                >
                  비밀번호 변경
                </Button>
                <Button
                  type="button"
                  className="flex-1 bg-stone-300 text-white hover:bg-stone-400"
                  onClick={moveToLoginPage}
                >
                  취소
                </Button>
              </div>
            </StepperContent>
            <StepperContent value={4} key={4}>
              <div className="w-full flex flex-row justify-end items-center gap-5">
                <Button
                  type="button"
                  className="bg-stone-500 text-white hover:bg-stone-400"
                  onClick={moveToLoginPage}
                >
                  로그인 화면으로 이동
                </Button>
              </div>
            </StepperContent>
          </StepperPanel>
        </CardFooter>
      </Card>
    </Stepper>
  )
}