"use client";

import { Suspense, useEffect, useState, type FormEvent } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";

import { ArrowLeft, Eye, EyeOff } 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 { isApiError } from "@/lib/apiError";
import { useAppSettings } from "@/hooks/queries/useSettings";
import { useAuth } from "@/hooks/useAuth";
import { useTranslation } from "@/hooks/useTranslation";

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const OTP_LENGTH = 6;
const RESEND_SECONDS = 60;
const MIN_PASSWORD = 8;

export default function RegisterPage() {
  return (
    <Suspense fallback={<div className="h-64" />}>
      <RegisterForm />
    </Suspense>
  );
}

function RegisterForm() {
  const { t } = useTranslation();
  const { signUp, completeEmailVerification } = useAuth();
  const { policyAgreementRequired, emailVerificationRequired } = useAppSettings();
  const router = useRouter();
  const params = useSearchParams();

  // ?verify=1 → user came from login with unverified email; skip step 1
  const [step, setStep] = useState<1 | 2>(params.get("verify") === "1" ? 2 : 1);
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [policy, setPolicy] = useState(false);
  const [showPw, setShowPw] = useState(false);
  const [errors, setErrors] = useState<Record<string, string | undefined>>({});
  const [formError, setFormError] = useState("");
  const [submitting, setSubmitting] = useState(false);

  const [otp, setOtp] = useState("");
  const [otpError, setOtpError] = useState("");
  const [resendIn, setResendIn] = useState(RESEND_SECONDS);
  const [resendError, setResendError] = useState("");

  useEffect(() => {
    if (step !== 2 || resendIn <= 0) return;
    const id = window.setTimeout(() => setResendIn((s) => s - 1), 1000);
    return () => window.clearTimeout(id);
  }, [step, resendIn]);

  function handleStep1Error(err: unknown) {
    if (isApiError(err) && err.kind === "validation" && err.fieldErrors) {
      setErrors({
        firstName: err.fieldError("firstname"),
        lastName: err.fieldError("lastname"),
        email: err.fieldError("email"),
        password: err.fieldError("password"),
        policy: err.fieldError("policy"),
      });
    } else {
      setFormError(isApiError(err) ? err.message : t("app.auth.errors.generic"));
    }
  }

  async function submitStep1(e: FormEvent) {
    e.preventDefault();
    const next: Record<string, string | undefined> = {};
    if (!firstName) next.firstName = t("app.auth.errors.nameRequired");
    if (!lastName) next.lastName = t("app.auth.errors.nameRequired");
    if (!email) next.email = t("app.auth.errors.emailRequired");
    else if (!EMAIL_RE.test(email)) next.email = t("app.auth.errors.emailInvalid");
    if (!password) next.password = t("app.auth.errors.passwordRequired");
    else if (password.length < MIN_PASSWORD) next.password = t("app.auth.errors.passwordShort");
    if (policyAgreementRequired && !policy) next.policy = t("app.auth.errors.policyRequired");
    setErrors(next);
    if (Object.values(next).some(Boolean)) return;

    setSubmitting(true);
    setFormError("");
    try {
      await signUp({ firstname: firstName, lastname: lastName, email, password, policy });
      if (!emailVerificationRequired) {
        router.replace("/dashboard");
        return;
      }
      setStep(2);
      setResendIn(RESEND_SECONDS);
    } catch (err) {
      handleStep1Error(err);
    } finally {
      setSubmitting(false);
    }
  }

  async function submitStep2(e: FormEvent) {
    e.preventDefault();
    if (otp.length !== OTP_LENGTH) {
      setOtpError(t("app.auth.errors.otpInvalid"));
      return;
    }
    setOtpError("");
    setSubmitting(true);
    try {
      await authApi.verifyRegistrationCode({ code: otp });
      // signIn withholds the session while email is unverified (verify=1 path arrives
      // with no user set yet) — this is what actually promotes it now that the code
      // is confirmed. Harmless no-op refresh for the signUp-originated path, where
      // signUp already set the session.
      await completeEmailVerification();
      router.replace("/dashboard");
    } catch (err) {
      setOtpError(isApiError(err) ? err.message : t("app.auth.errors.generic"));
      setSubmitting(false);
    }
  }

  async function resend() {
    if (resendIn > 0) return;
    setResendError("");
    try {
      await authApi.resendRegistrationCode();
      setResendIn(RESEND_SECONDS);
    } catch (err) {
      // 400/422 business errors ("resend cooldown") are silent by policy — the
      // caller owns them (Rule 29.1). Surface it here instead of dropping it.
      // Backend message is English-only; translate the known cooldown shape
      // ("...after N seconds") and fall back to the raw message otherwise.
      if (isApiError(err)) {
        const seconds = err.message.match(/(\d+)\s*seconds?/i)?.[1];
        setResendError(
          seconds
            ? t("app.auth.errors.resendCooldown").replace("{seconds}", seconds)
            : err.message,
        );
      } else {
        setResendError(t("app.auth.errors.generic"));
      }
    }
  }

  if (step === 1) {
    return (
      <div>
        <h1 className="text-2xl font-bold text-slate-900 dark:text-white sm:text-3xl">
          {t("app.auth.register.title")}
        </h1>
        <p className="mt-2 text-sm text-slate-600 dark:text-slate-300">
          {t("app.auth.register.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={submitStep1} className="mt-8 space-y-4">
          <div className="grid grid-cols-2 gap-3">
            <FormField
              label={t("app.auth.register.firstname")}
              autoComplete="given-name"
              value={firstName}
              onChange={(e) => setFirstName(e.target.value)}
              error={errors.firstName}
              required
            />
            <FormField
              label={t("app.auth.register.lastname")}
              autoComplete="family-name"
              value={lastName}
              onChange={(e) => setLastName(e.target.value)}
              error={errors.lastName}
              required
            />
          </div>
          <FormField
            label={t("app.auth.register.email")}
            type="email"
            autoComplete="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            error={errors.email}
            required
          />
          <FormField
            label={t("app.auth.register.password")}
            type={showPw ? "text" : "password"}
            autoComplete="new-password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            error={errors.password}
            hint={password ? t("app.auth.register.passwordHint") : undefined}
            required
            trailing={
              <button
                type="button"
                onClick={() => setShowPw((v) => !v)}
                aria-label={showPw ? "Hide password" : "Show password"}
                className="inline-flex h-8 w-8 items-center justify-center rounded-full text-slate-500 transition hover:bg-slate-100 dark:text-slate-400 dark:hover:bg-slate-800"
              >
                {showPw ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
              </button>
            }
          />

          {policyAgreementRequired && (
            <div>
              <label className="flex items-start gap-2.5 text-sm text-slate-600 dark:text-slate-300">
                <input
                  type="checkbox"
                  checked={policy}
                  onChange={(e) => setPolicy(e.target.checked)}
                  className="mt-0.5 h-4 w-4 rounded border-slate-300 text-brand-600 focus:ring-brand-500 dark:border-slate-600 dark:bg-slate-800"
                />
                <span>{t("app.auth.register.policy")}</span>
              </label>
              {errors.policy && (
                <p className="mt-1.5 text-xs font-medium text-rose-600 dark:text-rose-400">
                  {errors.policy}
                </p>
              )}
            </div>
          )}

          <Button type="submit" size="md" loading={submitting} className="w-full font-bold">
            {submitting ? t("app.auth.register.submitting") : t("app.auth.register.next")}
          </Button>
        </form>

        <p className="mt-8 text-center text-sm text-slate-600 dark:text-slate-300">
          {t("app.auth.register.hasAccount")}{" "}
          <Link
            href="/login"
            className="font-semibold text-brand-600 hover:text-brand-700 dark:text-brand-300"
          >
            {t("app.auth.register.signIn")}
          </Link>
        </p>
      </div>
    );
  }

  return (
    <div>
      <button
        type="button"
        onClick={() => setStep(1)}
        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.register.back")}
      </button>

      <h1 className="text-2xl font-bold text-slate-900 dark:text-white sm:text-3xl">
        {t("app.auth.register.step2Title")}
      </h1>
      <p className="mt-2 text-sm text-slate-600 dark:text-slate-300">
        {t("app.auth.register.step2Subtitle")}
      </p>

      <form onSubmit={submitStep2} className="mt-8 space-y-6">
        <div>
          <label className="mb-3 block text-center text-xs font-semibold capitalize tracking-wide text-slate-500 dark:text-slate-400">
            {t("app.auth.register.otpTitle")}
          </label>
          <OtpInput
            value={otp}
            onChange={(v) => {
              setOtp(v);
              setOtpError("");
            }}
            ariaLabel={t("app.auth.register.otpTitle")}
            autoFocus
            invalid={!!otpError}
          />
          {otpError && (
            <p className="mt-3 text-center text-xs font-medium text-rose-600 dark:text-rose-400">
              {otpError}
            </p>
          )}
        </div>

        <div className="text-center text-sm text-slate-600 dark:text-slate-300">
          {t("app.auth.register.otpSubtitle")}{" "}
          {resendIn > 0 ? (
            <span className="font-semibold text-slate-500">
              {t("app.auth.register.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.register.otpResend")}
            </button>
          )}
          {resendError && (
            <p role="alert" className="mt-2 text-xs font-medium text-rose-600 dark:text-rose-400">
              {resendError}
            </p>
          )}
        </div>

        <Button type="submit" size="md" loading={submitting} className="w-full font-bold">
          {t("app.auth.register.otpVerify")}
        </Button>
      </form>
    </div>
  );
}
