import { randomBytes, scrypt as _scrypt, timingSafeEqual, createHash, ScryptOptions } from 'crypto';

function scryptAsync(password: string, salt: Buffer, keylen: number, options: ScryptOptions): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    _scrypt(password, salt, keylen, options, (err, derivedKey) => {
      if (err) return reject(err);
      resolve(derivedKey as Buffer);
    });
  });
}

// 生成基于 scrypt 的密码哈希。格式：scrypt:N,r,p,saltHex,hashHex
export async function hashPassword(password: string): Promise<string> {
  const salt = randomBytes(16);
  const N = 16384; // 2^14
  const r = 8;
  const p = 1;
  const keyLen = 64;
  const derived = await scryptAsync(password, salt, keyLen, { N, r, p });
  return `scrypt:${N},${r},${p}:${salt.toString('hex')}:${Buffer.from(derived).toString('hex')}`;
}

export async function verifyPassword(password: string, stored: string): Promise<boolean> {
  try {
    const [algo, params, saltHex, hashHex] = stored.split(':');
    if (algo !== 'scrypt') return false;
    const [Nstr, rStr, pStr] = params.split(',');
    const N = Number(Nstr);
    const r = Number(rStr);
    const p = Number(pStr);
    const salt = Buffer.from(saltHex, 'hex');
    const expected = Buffer.from(hashHex, 'hex');
    const derived = await scryptAsync(password, salt, expected.length, { N, r, p });
    return timingSafeEqual(Buffer.from(derived), expected);
  } catch {
    return false;
  }
}

export function sha256Hex(input: string | Buffer): string {
  return createHash('sha256').update(input).digest('hex');
}
