/**
 * 密碼政策（與後端 ValidatePasswordPolicy 完全一致）：
 * - 至少 12 字元
 * - 含大寫、小寫、數字、符號
 *
 * 使用者可見說明（語言包，勿在 UI 另寫一句）：
 * - zh: password.policy.hint / api.err.400003
 *   「密碼須至少 12 碼，且含大寫、小寫、數字與符號」
 * - en: 同 key
 *   「Password must be at least 12 characters with upper, lower, digit, and symbol」
 * 後端 API 400003 message 使用上述英文句；FE 依 code 轉語言包。
 */

/** 與後端 domain.PasswordMinLen 一致 */
export const PASSWORD_MIN_LEN = 12;

/** 與後端 domain.PasswordPolicyZH / FE password.policy.hint 一致 */
export const PASSWORD_POLICY_ZH =
  "密碼須至少 12 碼，且含大寫、小寫、數字與符號";

/** 與後端 domain.PasswordPolicyEN / API 400003 / FE en password.policy.hint 一致 */
export const PASSWORD_POLICY_EN =
  "Password must be at least 12 characters with upper, lower, digit, and symbol";

export type PasswordPolicyResult = {
  ok: boolean;
  /** i18n key under password.policy.* or empty if ok */
  errorKey?: string;
};

const HAS_UPPER = /[A-Z]/;
const HAS_LOWER = /[a-z]/;
const HAS_DIGIT = /[0-9]/;
/** 符號：非字母數字（與後端 unicode.IsPunct/Symbol 大致對齊） */
const HAS_SYMBOL = /[^A-Za-z0-9]/;

export function checkPasswordPolicy(password: string): PasswordPolicyResult {
  const p = password ?? "";
  // 任一條件不符都回同一句（與後端 400003 / password.policy.hint 一致，不拆多種文案）
  const ok =
    [...p].length >= PASSWORD_MIN_LEN &&
    HAS_UPPER.test(p) &&
    HAS_LOWER.test(p) &&
    HAS_DIGIT.test(p) &&
    HAS_SYMBOL.test(p);
  if (!ok) {
    return { ok: false, errorKey: "password.policy.hint" };
  }
  return { ok: true };
}

/** 是否符合政策（提交前 gate） */
export function isPasswordPolicyOk(password: string): boolean {
  return checkPasswordPolicy(password).ok;
}

/** 產生符合政策的臨時密碼（mock admin 用） */
export function generateTempPassword(): string {
  const lower = "abcdefghijkmnopqrstuvwxyz";
  const upper = "ABCDEFGHJKLMNPQRSTUVWXYZ";
  const digits = "23456789";
  const symbols = "!@#$%^&*+-=";
  const all = lower + upper + digits + symbols;
  const pick = (s: string) => s[Math.floor(Math.random() * s.length)]!;
  const chars = [pick(lower), pick(upper), pick(digits), pick(symbols)];
  while (chars.length < 16) chars.push(pick(all));
  for (let i = chars.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [chars[i], chars[j]] = [chars[j]!, chars[i]!];
  }
  return chars.join("");
}
