"use client";

import { useEffect, useState, type FormEvent } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";

import { ArrowLeft } from "lucide-react";

import { authApi } from "@/api/auth.api";
import { Button } from "@/components/common/Button";
import { FormField } from "@/components/app/FormField";
import { OtpInput } from "@/components/app/OtpInput";
import { OTP_LENGTH, OTP_RESEND_SECONDS, PASSWORD_RESET_TOKEN_KEY } from "@/constants/auth";
import { isApiError } from "@/lib/apiError";
import { useTranslation } from "@/hooks/useTranslation";

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function tokenOf(res: unknown): string {
  const record = res as Record<string, unknown> | null;
  return record && typeof record.token === "string" ? record.token : "";
}

export default function ForgotPasswordPage() {
  const { t } = useTranslation();
  const router = useRouter();

  const [stage, setStage] = useState<"email" | "code">("email");
  const [email, setEmail] = useState("");
  const [flowToken, setFlowToken] = useState("");

  const [emailError, setEmailError] = useState("");
  const [formError, setFormError] = useState("");
  const [loading, setLoading] = useState(false);

  const [code, setCode] = useState("");
  const [codeError, setCodeError] = useState("");
  const [resendIn, setResendIn] = useState(OTP_RESEND_SECONDS);

  useEffect(() => {
    if (stage !== "code" || resendIn <= 0) return;
    const id = window.setTimeout(() => setResendIn((s) => s - 1), 1000);
    return () => window.clearTimeout(id);
  }, [stage, resendIn]);

  async function submitEmail(e: FormEvent) {
    e.preventDefault();
    if (!email) return setEmailError(t("app.auth.errors.emailRequired"));
    if (!EMAIL_RE.test(email)) return setEmailError(t("app.auth.errors.emailInvalid"));
    setEmailError("");
    setFormError("");
    setLoading(true);
    try {
      const res = await authApi.forgotFindUser({ credentials: email });
      setFlowToken(tokenOf(res));
      setStage("code");
      setResendIn(OTP_RESEND_SECONDS);
    } catch (err) {
      if (isApiError(err) && err.kind === "validation") {
        setEmailError(err.fieldError("credentials") ?? err.message);
      } else {
        setFormError(isApiError(err) ? err.message : t("app.auth.errors.generic"));
      }
    } finally {
      setLoading(false);
    }
  }

  async function submitCode(e: FormEvent) {
    e.preventDefault();
    if (code.length !== OTP_LENGTH) return setCodeError(t("app.auth.errors.otpInvalid"));
    setCodeError("");
    setLoading(true);
    try {
      const res = await authApi.forgotVerifyCode({ token: flowToken, code });
      // Carry the verified reset token to the reset-password page (sessionStorage, not URL).
      const resetToken = tokenOf(res) || flowToken;
      sessionStorage.setItem(PASSWORD_RESET_TOKEN_KEY, resetToken);
      router.replace("/reset-password");
    } catch (err) {
      setCodeError(isApiError(err) ? err.message : t("app.auth.errors.generic"));
      setLoading(false);
    }
  }

  async function resend() {
    if (resendIn > 0 || !flowToken) return;
    try {
      await authApi.forgotResendCode(flowToken);
      setResendIn(OTP_RESEND_SECONDS);
    } catch {
      /* transport errors surfaced by the interceptor */
    }
  }

  if (stage === "code") {
    return (
      <div>
        <button
          type="button"
          onClick={() => setStage("email")}
          className="mb-6 inline-flex items-center gap-1.5 text-sm font-semibold text-slate-600 transition hover:text-brand-600 dark:text-slate-300 dark:hover:text-brand-300"
        >
          <ArrowLeft className="h-4 w-4" />
          {t("app.auth.forgot.back")}
        </button>

        <h1 className="text-2xl font-bold text-slate-900 dark:text-white sm:text-3xl">
          {t("app.auth.forgot.codeTitle")}
        </h1>
        <p className="mt-2 text-sm text-slate-600 dark:text-slate-300">
          {t("app.auth.forgot.codeSubtitle").replace("{email}", email)}
        </p>

        <form onSubmit={submitCode} className="mt-8 space-y-6">
          <div>
            <OtpInput
              value={code}
              onChange={(v) => {
                setCode(v);
                setCodeError("");
              }}
              ariaLabel={t("app.auth.forgot.codeTitle")}
              autoFocus
              invalid={!!codeError}
            />
            {codeError && (
              <p className="mt-3 text-center text-xs font-medium text-rose-600 dark:text-rose-400">
                {codeError}
              </p>
            )}
          </div>

          <div className="text-center text-sm text-slate-600 dark:text-slate-300">
            {t("app.auth.forgot.otpSubtitle")}{" "}
            {resendIn > 0 ? (
              <span className="font-semibold text-slate-500">
                {t("app.auth.forgot.otpResendIn").replace("{seconds}", String(resendIn))}
              </span>
            ) : (
              <button
                type="button"
                onClick={resend}
                className="font-semibold text-brand-600 hover:text-brand-700 dark:text-brand-300"
              >
                {t("app.auth.forgot.otpResend")}
              </button>
            )}
          </div>

          <Button type="submit" size="md" loading={loading} className="w-full font-bold">
            {loading ? t("app.auth.forgot.verifying") : t("app.auth.forgot.verify")}
          </Button>
        </form>
      </div>
    );
  }

  return (
    <div>
      <h1 className="text-2xl font-bold text-slate-900 dark:text-white sm:text-3xl">
        {t("app.auth.forgot.title")}
      </h1>
      <p className="mt-2 text-sm text-slate-600 dark:text-slate-300">
        {t("app.auth.forgot.subtitle")}
      </p>

      {formError && (
        <p
          role="alert"
          className="mt-6 rounded-xl bg-rose-50 px-4 py-3 text-sm font-medium text-rose-700 dark:bg-rose-500/10 dark:text-rose-300"
        >
          {formError}
        </p>
      )}

      <form noValidate onSubmit={submitEmail} className="mt-8 space-y-4">
        <FormField
          label={t("app.auth.forgot.email")}
          type="email"
          autoComplete="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          error={emailError}
          required
        />
        <Button type="submit" size="md" loading={loading} className="w-full font-bold">
          {loading ? t("app.auth.forgot.submitting") : t("app.auth.forgot.submit")}
        </Button>
      </form>

      <Link
        href="/login"
        className="mt-8 inline-flex items-center gap-1.5 text-sm font-semibold text-slate-600 transition hover:text-brand-600 dark:text-slate-300 dark:hover:text-brand-300"
      >
        <ArrowLeft className="h-4 w-4" />
        {t("app.auth.forgot.back")}
      </Link>
    </div>
  );
}
