// Client-side password helpers for the Users admin flows.
//
// The server is authoritative on password policy (it enforces a >= 8 char
// minimum). These helpers are purely for UX: a generator for "make me a strong
// one" and a lightweight strength hint shown next to the field. Neither value
// is ever logged or persisted beyond the live form state.

// Mirrors the server's generator charset (server/src/auth/password.rs) — an
// unambiguous alphanumeric set plus a few symbols, with confusable characters
// (0/O, 1/l/I) already excluded so a generated password is safe to read aloud.
const CHARSET =
  "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%";

/**
 * Generate a cryptographically-random password of `length` chars using the
 * Web Crypto API (never Math.random). Rejection-samples so every character is
 * uniformly distributed across the charset with no modulo bias.
 */
export function generatePassword(length = 20): string {
  const max = Math.floor(256 / CHARSET.length) * CHARSET.length;
  const out: string[] = [];
  const buf = new Uint8Array(1);
  while (out.length < length) {
    crypto.getRandomValues(buf);
    const byte = buf[0];
    if (byte < max) out.push(CHARSET[byte % CHARSET.length]);
  }
  return out.join("");
}

export type StrengthLevel = "weak" | "fair" | "strong";

export interface PasswordStrength {
  level: StrengthLevel;
  /** Human hint shown under the field. */
  hint: string;
  /** True once the server's hard minimum (8 chars) is met. */
  meetsMinimum: boolean;
}

/**
 * A pragmatic strength hint (NOT a security gate — the server enforces policy).
 * Scores length and character-class variety; the bar is intentionally simple
 * and advisory so an admin understands when a password is thin.
 */
export function scorePassword(password: string): PasswordStrength {
  const len = password.length;
  const meetsMinimum = len >= 8;

  if (len === 0) {
    return { level: "weak", hint: "", meetsMinimum: false };
  }
  if (!meetsMinimum) {
    return {
      level: "weak",
      hint: "Too short — at least 8 characters required.",
      meetsMinimum: false,
    };
  }

  let classes = 0;
  if (/[a-z]/.test(password)) classes++;
  if (/[A-Z]/.test(password)) classes++;
  if (/[0-9]/.test(password)) classes++;
  if (/[^A-Za-z0-9]/.test(password)) classes++;

  if (len >= 14 && classes >= 3) {
    return { level: "strong", hint: "Strong password.", meetsMinimum: true };
  }
  if (len >= 10 && classes >= 2) {
    return {
      level: "fair",
      hint: "Fair — longer with more character variety is stronger.",
      meetsMinimum: true,
    };
  }
  return {
    level: "fair",
    hint: "Acceptable, but a longer, more varied password is recommended.",
    meetsMinimum: true,
  };
}
