import assert from 'node:assert/strict';
import { test } from 'node:test';
import {
  hashPassword,
  hashPasswordAsync,
  isLegacyPasswordHash,
  verifyPassword,
  verifyPasswordAsync,
  verifyScryptPasswordAsync,
  verifyScryptPassword,
  verifyVestaPassword
} from '../src/password-hash.js';

test('hashes and verifies current scrypt passwords', () => {
  const stored = hashPassword('correct horse battery staple');

  assert.match(stored, /^scrypt\$[0-9a-f]{32}\$[0-9a-f]{128}$/);
  assert.equal(verifyScryptPassword('correct horse battery staple', stored), true);
  assert.equal(verifyPassword('correct horse battery staple', stored), true);
  assert.equal(verifyPassword('wrong password', stored), false);
});

test('hashes and verifies current scrypt passwords asynchronously', async () => {
  const stored = await hashPasswordAsync('correct horse battery staple');

  assert.match(stored, /^scrypt\$[0-9a-f]{32}\$[0-9a-f]{128}$/);
  assert.equal(await verifyScryptPasswordAsync('correct horse battery staple', stored), true);
  assert.equal(await verifyPasswordAsync('correct horse battery staple', stored), true);
  assert.equal(await verifyPasswordAsync('wrong password', stored), false);
});

test('verifies Vesta MD5-CRYPT passwords with known vectors', () => {
  const passwordVector = '$1$hfT7jp2q$G3yf0NUx7mUkX.LIFWQxN.';
  const unicodeVector = '$1$salt1234$VwTk0ScCcREDNl.8aCJCc0';

  assert.equal(verifyVestaPassword('password', `{MD5}${passwordVector}`), true);
  assert.equal(verifyVestaPassword('password', `{MD5-CRYPT}${passwordVector}`), true);
  assert.equal(verifyVestaPassword('pässwörd', unicodeVector), true);
  assert.equal(verifyPassword('password', `{MD5}${passwordVector}`), true);
  assert.equal(verifyVestaPassword('wrong password', `{MD5}${passwordVector}`), false);
});

test('detects only supported legacy password hashes', () => {
  assert.equal(isLegacyPasswordHash('{MD5}$1$12345678$xek.CpjQUVgdf/P2N9KQf/'), true);
  assert.equal(isLegacyPasswordHash('{MD5-CRYPT}$1$12345678$xek.CpjQUVgdf/P2N9KQf/'), true);
  assert.equal(isLegacyPasswordHash('$1$12345678$xek.CpjQUVgdf/P2N9KQf/'), true);
  assert.equal(isLegacyPasswordHash('{SHA256-CRYPT}$5$salt$hash'), false);
  assert.equal(isLegacyPasswordHash('{MD5}$1$toolongsalt$invalid'), false);
  assert.equal(verifyPassword('password', 'malformed'), false);
});
