"use client";

import { useCallback, useRef, useState, type FormEvent } from "react";
import { authDict } from "@/features/auth/dict";
import {
  isCompleteOtp,
  normalizeOtpInput,
  OTP_LENGTH,
  useWebOtp,
} from "@/features/auth/hooks/use-web-otp";
import {
  useCheckPhone,
  usePasswordLogin,
  useSendOtp,
  useVerifyOtp,
} from "@/features/auth/hooks/use-login";
import { toEnglishDigits } from "@/lib/to-english-digits";

type LoginStep = "phone" | "password" | "otp";

function isValidPhoneNumber(phoneNumber: string) {
  return /^\d{11}$/.test(phoneNumber);
}

export function LoginForm() {
  const [step, setStep] = useState<LoginStep>("phone");
  const [phoneNumber, setPhoneNumber] = useState("");
  const [password, setPassword] = useState("");
  const [otp, setOtp] = useState("");
  const [canUsePassword, setCanUsePassword] = useState(false);
  const [errors, setErrors] = useState<{
    phoneNumber?: string;
    password?: string;
    otp?: string;
  }>({});
  const submitLockRef = useRef(false);

  const checkPhoneMutation = useCheckPhone();
  const sendOtpMutation = useSendOtp();
  const verifyOtpMutation = useVerifyOtp();
  const passwordLoginMutation = usePasswordLogin();

  const normalizedPhone = toEnglishDigits(phoneNumber).trim();
  const canContinue = isValidPhoneNumber(normalizedPhone);
  const isPending =
    checkPhoneMutation.isPending ||
    sendOtpMutation.isPending ||
    verifyOtpMutation.isPending ||
    passwordLoginMutation.isPending;

  const resetToPhoneStep = () => {
    setStep("phone");
    setPassword("");
    setOtp("");
    setCanUsePassword(false);
    setErrors({});
    submitLockRef.current = false;
  };

  const goToOtpStep = useCallback(() => {
    sendOtpMutation.mutate(
      { phoneNumber: normalizedPhone },
      {
        onSuccess: () => {
          setStep("otp");
          setOtp("");
          submitLockRef.current = false;
        },
      },
    );
  }, [normalizedPhone, sendOtpMutation]);

  const submitOtp = useCallback(
    (rawCode: string) => {
      const code = normalizeOtpInput(toEnglishDigits(rawCode));

      if (!code) {
        setErrors({ otp: authDict.login.otpRequired });
        return;
      }

      if (submitLockRef.current || verifyOtpMutation.isPending) {
        return;
      }

      submitLockRef.current = true;
      setOtp(code);
      setErrors({});

      verifyOtpMutation.mutate(
        {
          phoneNumber: normalizedPhone,
          code,
        },
        {
          onSettled: () => {
            submitLockRef.current = false;
          },
        },
      );
    },
    [normalizedPhone, verifyOtpMutation],
  );

  const handleOtpReceived = useCallback(
    (code: string) => {
      const normalized = normalizeOtpInput(toEnglishDigits(code));
      setOtp(normalized);

      if (isCompleteOtp(normalized)) {
        submitOtp(normalized);
      }
    },
    [submitOtp],
  );

  useWebOtp({
    enabled: step === "otp" && !isPending,
    onCode: handleOtpReceived,
  });

  const handlePhoneSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    const phone = toEnglishDigits(phoneNumber).trim();

    if (!phone) {
      setErrors({ phoneNumber: authDict.login.phoneRequired });
      return;
    }

    if (!isValidPhoneNumber(phone)) {
      setErrors({ phoneNumber: authDict.login.phoneInvalid });
      return;
    }

    setPhoneNumber(phone);
    setErrors({});

    checkPhoneMutation.mutate(
      { phoneNumber: phone },
      {
        onSuccess: (data) => {
          setCanUsePassword(data.hasPassword);

          if (data.hasPassword) {
            setStep("password");
            setPassword("");
            return;
          }

          sendOtpMutation.mutate(
            { phoneNumber: phone },
            {
              onSuccess: () => {
                setStep("otp");
                setOtp("");
                submitLockRef.current = false;
              },
            },
          );
        },
      },
    );
  };

  const handlePasswordSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (!password.trim()) {
      setErrors({ password: authDict.login.passwordRequired });
      return;
    }

    setErrors({});
    passwordLoginMutation.mutate({
      phoneNumber: normalizedPhone,
      password,
    });
  };

  const handleOtpSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    submitOtp(otp);
  };

  const inputClassName =
    "h-12 w-full rounded-2xl border-0 bg-input px-4 text-sm text-foreground shadow-soft-sm outline-none ring-1 ring-border transition-shadow placeholder:text-muted-foreground focus:ring-2 focus:ring-primary";

  if (step === "password") {
    return (
      <form
        onSubmit={handlePasswordSubmit}
        className="flex w-full flex-col gap-6"
        noValidate
      >
        <div className="space-y-2 text-center">
          <h1 className="text-2xl font-bold text-card-foreground">
            {authDict.login.title}
          </h1>
          <p className="text-sm leading-7 text-muted-foreground">
            {authDict.login.passwordHint.replace("{phone}", normalizedPhone)}
          </p>
        </div>

        <div className="space-y-2">
          <label
            htmlFor="password"
            className="block text-sm font-medium text-card-foreground"
          >
            {authDict.login.passwordLabel}
          </label>
          <input
            id="password"
            name="password"
            type="password"
            autoComplete="current-password"
            autoFocus
            dir="ltr"
            value={password}
            onChange={(event) => {
              setPassword(event.target.value);

              if (errors.password) {
                setErrors((current) => ({ ...current, password: undefined }));
              }
            }}
            placeholder={authDict.login.passwordPlaceholder}
            className={`${inputClassName} text-start`}
          />
          {errors.password ? (
            <p className="text-sm text-destructive">{errors.password}</p>
          ) : null}
        </div>

        <button
          type="submit"
          disabled={isPending || !password.trim()}
          className="inline-flex h-12 items-center justify-center rounded-2xl bg-primary px-6 text-sm font-semibold text-primary-foreground shadow-soft-sm transition-all hover:brightness-105 disabled:cursor-not-allowed disabled:opacity-70"
        >
          {passwordLoginMutation.isPending
            ? authDict.login.submittingPassword
            : authDict.login.submitPassword}
        </button>

        <button
          type="button"
          onClick={goToOtpStep}
          disabled={isPending}
          className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-70"
        >
          {authDict.login.useOtpInstead}
        </button>

        <button
          type="button"
          onClick={resetToPhoneStep}
          disabled={isPending}
          className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-70"
        >
          {authDict.login.changePhone}
        </button>
      </form>
    );
  }

  if (step === "otp") {
    return (
      <form
        onSubmit={handleOtpSubmit}
        className="flex w-full flex-col gap-6"
        noValidate
      >
        <div className="space-y-2 text-center">
          <h1 className="text-2xl font-bold text-card-foreground">
            {authDict.login.title}
          </h1>
          <p className="text-sm leading-7 text-muted-foreground">
            {authDict.login.otpSentHint.replace("{phone}", normalizedPhone)}
          </p>
        </div>

        <div className="space-y-2">
          <label
            htmlFor="otp"
            className="block text-sm font-medium text-card-foreground"
          >
            {authDict.login.otpLabel}
          </label>
          <input
            id="otp"
            name="one-time-code"
            type="text"
            inputMode="numeric"
            autoComplete="one-time-code"
            autoFocus
            maxLength={OTP_LENGTH}
            pattern="[0-9]*"
            dir="ltr"
            value={otp}
            onChange={(event) => {
              const next = normalizeOtpInput(toEnglishDigits(event.target.value));
              setOtp(next);

              if (errors.otp) {
                setErrors((current) => ({ ...current, otp: undefined }));
              }

              if (isCompleteOtp(next)) {
                submitOtp(next);
              }
            }}
            placeholder={authDict.login.otpPlaceholder}
            className="h-12 w-full rounded-2xl border-0 bg-input px-4 text-center text-lg tracking-[0.3em] text-foreground shadow-soft-sm outline-none ring-1 ring-border transition-shadow placeholder:text-sm placeholder:tracking-normal placeholder:text-muted-foreground focus:ring-2 focus:ring-primary"
          />
          {errors.otp ? (
            <p className="text-sm text-destructive">{errors.otp}</p>
          ) : null}
        </div>

        <button
          type="submit"
          disabled={isPending || !isCompleteOtp(otp)}
          className="inline-flex h-12 items-center justify-center rounded-2xl bg-primary px-6 text-sm font-semibold text-primary-foreground shadow-soft-sm transition-all hover:brightness-105 disabled:cursor-not-allowed disabled:opacity-70"
        >
          {verifyOtpMutation.isPending
            ? authDict.login.submittingOtp
            : authDict.login.submitOtp}
        </button>

        {canUsePassword ? (
          <button
            type="button"
            onClick={() => {
              setStep("password");
              setOtp("");
              setErrors({});
              submitLockRef.current = false;
            }}
            disabled={isPending}
            className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-70"
          >
            {authDict.login.usePasswordInstead}
          </button>
        ) : null}

        <button
          type="button"
          onClick={resetToPhoneStep}
          disabled={isPending}
          className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-70"
        >
          {authDict.login.changePhone}
        </button>
      </form>
    );
  }

  return (
    <form
      onSubmit={handlePhoneSubmit}
      className="flex w-full flex-col gap-6"
      noValidate
    >
      <div className="space-y-2 text-center">
        <h1 className="text-2xl font-bold text-card-foreground">
          {authDict.login.title}
        </h1>
        <p className="text-sm leading-7 text-muted-foreground">
          {authDict.login.subtitle}
        </p>
      </div>

      <div className="space-y-2">
        <label
          htmlFor="phoneNumber"
          className="block text-sm font-medium text-card-foreground"
        >
          {authDict.login.phoneLabel}
        </label>
        <input
          id="phoneNumber"
          name="phoneNumber"
          type="tel"
          inputMode="numeric"
          autoComplete="tel"
          dir="ltr"
          value={phoneNumber}
          onChange={(event) => {
            setPhoneNumber(toEnglishDigits(event.target.value));
            if (errors.phoneNumber) {
              setErrors((current) => ({
                ...current,
                phoneNumber: undefined,
              }));
            }
          }}
          placeholder={authDict.login.phonePlaceholder}
          className={inputClassName}
        />
        {errors.phoneNumber ? (
          <p className="text-sm text-destructive">{errors.phoneNumber}</p>
        ) : null}
      </div>

      <button
        type="submit"
        disabled={isPending || !canContinue}
        className="inline-flex h-12 items-center justify-center rounded-2xl bg-primary px-6 text-sm font-semibold text-primary-foreground shadow-soft-sm transition-all hover:brightness-105 disabled:cursor-not-allowed disabled:opacity-70"
      >
        {checkPhoneMutation.isPending || sendOtpMutation.isPending
          ? authDict.login.submittingPhone
          : authDict.login.submitPhone}
      </button>
    </form>
  );
}
