"use client";

import { useState } from "react";

import { api, ApiError } from "@/lib/api/browser";

/**
 * The change-your-own-password form, shared by the forced screen and profile settings.
 *
 * One component because the two differ only in framing: the same three fields, the same
 * endpoint, the same rules. Two copies would drift, and the one that drifted would be the
 * forced screen — the one a new host meets first.
 *
 * Every rule it enforces is enforced again by the API. The confirmation field is the
 * exception and is client-only by nature: the server has no second value to compare.
 */
export default function PasswordFields({
  onChanged,
  submitLabel = "Change password",
  minLength = 12,
}: {
  onChanged: () => void;
  submitLabel?: string;
  minLength?: number;
}) {
  const [current, setCurrent] = useState("");
  const [next, setNext] = useState("");
  const [confirm, setConfirm] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const mismatch = confirm.length > 0 && next !== confirm;

  async function submit(event: React.FormEvent) {
    event.preventDefault();
    if (next !== confirm) {
      setError("The two new passwords do not match.");
      return;
    }
    setBusy(true);
    setError(null);
    try {
      await api.changeOwnPassword(current, next);
      setCurrent("");
      setNext("");
      setConfirm("");
      onChanged();
    } catch (err) {
      setError(
        err instanceof ApiError ? err.message : "Could not change the password. Try again.",
      );
      setBusy(false);
    }
  }

  return (
    <form onSubmit={submit} className="mt-6 space-y-3">
      <div>
        <label htmlFor="current-password" className="block text-xs font-medium text-stone-500">
          Current password
        </label>
        <input
          id="current-password"
          type="password"
          autoComplete="current-password"
          required
          value={current}
          onChange={(e) => setCurrent(e.target.value)}
          className="mt-1 w-full rounded-md border border-stone-300 px-3 py-2 text-sm focus:border-stone-500 focus:outline-none focus:ring-2 focus:ring-stone-200"
        />
      </div>

      <div>
        <label htmlFor="new-password" className="block text-xs font-medium text-stone-500">
          New password
        </label>
        <input
          id="new-password"
          type="password"
          autoComplete="new-password"
          required
          minLength={minLength}
          value={next}
          onChange={(e) => setNext(e.target.value)}
          aria-describedby="new-password-hint"
          className="mt-1 w-full rounded-md border border-stone-300 px-3 py-2 text-sm focus:border-stone-500 focus:outline-none focus:ring-2 focus:ring-stone-200"
        />
        <p id="new-password-hint" className="mt-1 text-xs text-stone-500">
          At least {minLength} characters. Length matters more than punctuation — a few
          ordinary words are stronger than one word with symbols in it.
        </p>
      </div>

      <div>
        <label htmlFor="confirm-password" className="block text-xs font-medium text-stone-500">
          Confirm new password
        </label>
        <input
          id="confirm-password"
          type="password"
          autoComplete="new-password"
          required
          value={confirm}
          onChange={(e) => setConfirm(e.target.value)}
          aria-invalid={mismatch || undefined}
          className={`mt-1 w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 ${
            mismatch
              ? "border-red-400 focus:border-red-500 focus:ring-red-100"
              : "border-stone-300 focus:border-stone-500 focus:ring-stone-200"
          }`}
        />
        {mismatch && <p className="mt-1 text-xs text-red-700">These do not match.</p>}
      </div>

      <button
        type="submit"
        disabled={busy || mismatch}
        className="w-full rounded-md bg-stone-900 px-4 py-2 text-sm font-medium text-white hover:bg-stone-800 disabled:opacity-50"
      >
        {busy ? "Saving…" : submitLabel}
      </button>

      {error && (
        <p role="alert" className="rounded-lg bg-red-50 px-3 py-2 text-sm text-red-700">
          {error}
        </p>
      )}
    </form>
  );
}
