"use client";

import * as React from "react";
import Link from "next/link";
import { useActionState } from "react";
import { ShieldCheck } from "lucide-react";
import { signInAction } from "@/lib/actions/auth";
import { authTexts } from "@/lib/i18n/auth";
import type { AuthActionState } from "@/lib/validation/auth";
import { FormAlert } from "../_components/form-alert";
import { SubmitButton } from "../_components/submit-button";
import { TextField } from "../_components/text-field";

export function SignInForm({
  callbackUrl,
  notice,
}: {
  callbackUrl: string;
  notice?: { tone: "error" | "info" | "success"; message: string } | null;
}) {
  const [state, formAction, pending] = useActionState<AuthActionState, FormData>(
    signInAction,
    null,
  );

  const [identifier, setIdentifier] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [otp, setOtp] = React.useState("");
  const formRef = React.useRef<HTMLFormElement>(null);

  const failure = state && state.ok === false ? state : null;
  const fieldErrors = failure?.fieldErrors ?? {};
  const needsOtp = failure?.code === "2FA_REQUIRED";

  React.useEffect(() => {
    if (!needsOtp) setOtp("");
  }, [needsOtp]);

  function resendCode() {
    setOtp("");
    // Submitting without a code makes the server issue a fresh one.
    window.setTimeout(() => formRef.current?.requestSubmit(), 0);
  }

  return (
    <form ref={formRef} action={formAction} className="space-y-5">
      <input type="hidden" name="callbackUrl" value={callbackUrl} />

      {notice && !failure ? (
        <FormAlert tone={notice.tone}>{notice.message}</FormAlert>
      ) : null}

      {failure && !needsOtp ? <FormAlert tone="error">{failure.error}</FormAlert> : null}

      <TextField
        id="identifier"
        name="identifier"
        label={authTexts.identifierLabel}
        placeholder={authTexts.identifierPlaceholder}
        autoComplete="username"
        value={identifier}
        onChange={setIdentifier}
        error={fieldErrors.identifier}
        disabled={pending}
        autoFocus
        required
      />

      <div>
        <TextField
          id="password"
          name="password"
          type="password"
          label={authTexts.passwordLabel}
          placeholder={authTexts.passwordPlaceholder}
          autoComplete="current-password"
          value={password}
          onChange={setPassword}
          error={fieldErrors.password}
          disabled={pending}
          required
        />
        <div className="mt-2 text-right">
          <Link
            href="/forgot-password"
            className="text-xs font-medium text-primary transition-colors hover:text-primary/80"
          >
            {authTexts.forgotPasswordLink}
          </Link>
        </div>
      </div>

      {needsOtp ? (
        <div className="space-y-3 rounded-xl border border-primary/20 bg-primary/5 p-4">
          <div className="flex items-start gap-2.5 text-sm text-foreground">
            <ShieldCheck className="mt-0.5 size-4 shrink-0 text-primary" />
            <p className="leading-relaxed text-muted-foreground">{authTexts.otpHint}</p>
          </div>
          <TextField
            id="otp"
            name="otp"
            label={authTexts.otpLabel}
            placeholder={authTexts.otpPlaceholder}
            autoComplete="one-time-code"
            inputMode="numeric"
            maxLength={6}
            value={otp}
            onChange={(next) => setOtp(next.replace(/\D/g, ""))}
            error={fieldErrors.otp}
            disabled={pending}
            className="[&_input]:font-mono [&_input]:tracking-[0.4em]"
          />
          <button
            type="button"
            onClick={resendCode}
            disabled={pending}
            className="text-xs font-medium text-primary transition-colors hover:text-primary/80 disabled:opacity-50"
          >
            {authTexts.otpResend}
          </button>
        </div>
      ) : (
        <input type="hidden" name="otp" value="" />
      )}

      <SubmitButton
        pending={pending}
        label={authTexts.signInSubmit}
        pendingLabel={authTexts.signInSubmitting}
      />
    </form>
  );
}

export default SignInForm;
