"use client";

import { Suspense, useState, type FormEvent } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { Eye, EyeOff } from "lucide-react";
import { Button } from "@/components/common/Button";
import { FormField } from "@/components/app/FormField";
import { USER_HOME } from "@/constants/routes";
import { isApiError } from "@/lib/apiError";
import { notify } from "@/lib/notify";
import { safeRedirect } from "@/lib/safeRedirect";
import { useAppSettings } from "@/hooks/queries/useSettings";
import { useAuth } from "@/hooks/useAuth";
import { useTranslation } from "@/hooks/useTranslation";

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

export default function LoginPage() {
  return (
    <Suspense fallback={<div className="h-64" />}>
      <LoginForm />
    </Suspense>
  );
}

function LoginForm() {
  const { t } = useTranslation();
  const { signIn } = useAuth();
  const { registrationEnabled } = useAppSettings();
  const router = useRouter();
  const params = useSearchParams();
  const redirectTo = safeRedirect(params.get("redirect"), USER_HOME, "user");

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [showPw, setShowPw] = useState(false);
  const [errors, setErrors] = useState<{ email?: string; password?: string }>({});
  const [formError, setFormError] = useState("");
  const [loading, setLoading] = useState(false);

  async function onSubmit(e: FormEvent) {
    e.preventDefault();
    const next: typeof errors = {};
    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");
    setErrors(next);
    if (Object.keys(next).length > 0) return;

    setLoading(true);
    setFormError("");
    try {
      const { requiresTwoFactor, requiresEmailVerification, banned } = await signIn({ email, password });
      if (banned) {
        setFormError(t("app.auth.errors.banned"));
        setLoading(false);
        return;
      }
      if (requiresTwoFactor) {
        router.replace("/two-factor");
      } else if (requiresEmailVerification) {
        router.replace("/register?verify=1");
      } else {
        router.replace(redirectTo);
      }
    } catch (err) {
      // Field errors land on the inputs; everything else (bad credentials, etc.) on the banner.
      if (isApiError(err) && err.kind === "validation" && err.fieldErrors) {
        setErrors({ email: err.fieldError("email"), password: err.fieldError("password") });
      } else {
        setFormError(isApiError(err) ? err.message : t("app.auth.errors.generic"));
      }
      setLoading(false);
    }
  }

  return (
    <div>
      <h1 className="text-2xl font-bold text-slate-900 dark:text-white sm:text-3xl">
        {t("app.auth.login.title")}
      </h1>
      <p className="mt-2 text-sm text-slate-600 dark:text-slate-300">
        {t("app.auth.login.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={onSubmit} className="mt-8 space-y-4">
        <FormField
          label={t("app.auth.login.email")}
          type="email"
          autoComplete="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          error={errors.email}
          required
        />
        <FormField
          label={t("app.auth.login.password")}
          type={showPw ? "text" : "password"}
          autoComplete="current-password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          error={errors.password}
          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>
          }
        />

        <div className="flex justify-end">
          <Link
            href="/forgot-password"
            className="text-xs font-semibold text-brand-600 hover:text-brand-700 dark:text-brand-300"
          >
            {t("app.auth.login.forgotPassword")}
          </Link>
        </div>

        <Button type="submit" size="md" loading={loading} className="w-full font-bold">
          {loading ? t("app.auth.login.submitting") : t("app.auth.login.submit")}
        </Button>
      </form>

      <p className="mt-8 text-center text-sm text-slate-600 dark:text-slate-300">
        {t("app.auth.login.noAccount")}{" "}
        {registrationEnabled ? (
          <Link
            href="/register"
            className="font-semibold text-brand-600 hover:text-brand-700 dark:text-brand-300"
          >
            {t("app.auth.login.signUp")}
          </Link>
        ) : (
          <button
            type="button"
            onClick={() => notify(t("app.auth.login.registrationClosed"), "info")}
            className="font-semibold text-brand-600 hover:text-brand-700 dark:text-brand-300"
          >
            {t("app.auth.login.signUp")}
          </button>
        )}
      </p>
    </div>
  );
}
