"use client";

import { useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  authDestination,
  postAuthRequest,
  type SafeAuthSession,
} from "./auth-client";

export function PasswordForm({
  mode,
  token = "",
  onComplete,
  onBusyChange,
}: {
  mode: "set" | "reset" | "change";
  token?: string;
  onComplete?: (session?: SafeAuthSession) => void;
  onBusyChange?: (busy: boolean) => void;
}) {
  const router = useRouter();
  const pending = useRef(false);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const prefix = `${mode}-password`;

  async function submit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (pending.current) return;
    const form = event.currentTarget;
    const fields = new FormData(form);
    const newPassword = String(fields.get("new_password") ?? "");
    const confirmation = String(fields.get("confirm_password") ?? "");
    const oldPassword = String(fields.get("old_password") ?? "");
    setError("");
    if (!newPassword || newPassword.length > 1024) {
      setError("Please enter a new password of no more than 1024 characters.");
      return;
    }
    if (newPassword !== confirmation) {
      setError("The new passwords do not match.");
      return;
    }
    if (mode === "change" && !oldPassword) {
      setError("Please enter your current password.");
      return;
    }
    if (mode === "reset" && !token) {
      setError(
        "The reset token is missing. Open the complete link from your reset email.",
      );
      return;
    }
    pending.current = true;
    setBusy(true);
    onBusyChange?.(true);
    const result = await postAuthRequest(`/api/auth/${mode}-password`, {
      new_password: newPassword,
      confirm_password: confirmation,
      ...(mode === "change" ? { old_password: oldPassword } : {}),
      ...(mode === "reset" ? { token } : {}),
    });
    pending.current = false;
    setBusy(false);
    onBusyChange?.(false);
    if (!result.ok) {
      setError(result.error);
      return;
    }
    if (mode !== "reset" && !result.session) {
      setError(
        "The authentication service did not return a valid session. Please try again.",
      );
      return;
    }
    form.reset();
    if (onComplete) onComplete(result.session);
    else
      router.replace(
        result.session ? authDestination(result.session) : "/signin",
      );
    router.refresh();
  }

  return (
    <form onSubmit={submit}>
      <fieldset disabled={busy} className="space-y-5" aria-busy={busy}>
        {mode === "change" && (
          <div>
            <label
              htmlFor={`${prefix}-old`}
              className="field-label text-auth-muted"
            >
              Current password
            </label>
            <Input
              id={`${prefix}-old`}
              name="old_password"
              type="password"
              autoComplete="current-password"
              required
              maxLength={1024}
            />
          </div>
        )}
        <div>
          <label
            htmlFor={`${prefix}-new`}
            className="field-label text-auth-muted"
          >
            New password
          </label>
          <Input
            id={`${prefix}-new`}
            name="new_password"
            type="password"
            autoComplete="new-password"
            required
            maxLength={1024}
          />
        </div>
        <div>
          <label
            htmlFor={`${prefix}-confirm`}
            className="field-label text-auth-muted"
          >
            Confirm new password
          </label>
          <Input
            id={`${prefix}-confirm`}
            name="confirm_password"
            type="password"
            autoComplete="new-password"
            required
            maxLength={1024}
          />
        </div>
        {error && (
          <p role="alert" className="text-sm text-destructive">
            {error}
          </p>
        )}
        <Button variant="auth" className="w-full" disabled={busy}>
          {busy && <Loader2 className="animate-spin" />}
          {busy
            ? "Saving..."
            : mode === "change"
              ? "Change password"
              : mode === "reset"
                ? "Reset password"
                : "Set password"}
        </Button>
      </fieldset>
    </form>
  );
}
