import { sign as jwtSign, verify as jwtVerify } from 'hono/jwt';
import { getKey } from 'officerdb/secret-store';

// The signing key comes from the secret store, not from JWT_SECRET in .env — see docs/secret-store.md.
//
// Read lazily and cached: importing this module must not open the store, because plenty of files import
// `sign`/`verify` for their types or for one code path they may never take.
//
// It is created on first use rather than required up front, which is a deliberate trade. There is no
// longer a startup error telling you the secret is missing; instead, losing the store file silently mints
// a new key and signs everyone out of every device. That is the same failure the old env var had — it was
// regenerated by the setup script on every run that agreed to rewrite .env — except the store is a file
// nobody edits by hand, so it is far less likely to happen by accident.
let cachedKey: string | null = null;
function signingKey(): string {
  if (!cachedKey) cachedKey = getKey('jwt');
  return cachedKey;
}

function parseExpiration(expiration: string): number {
  const match = expiration.match(/^(\d+)([smhd])$/);
  if (!match) {
    throw new Error(`Invalid expiration format: ${expiration}`);
  }
  const value = parseInt(match[1]!, 10);
  const unit = match[2];
  const multipliers: Record<string, number> = {
    s: 1,
    m: 60,
    h: 60 * 60,
    d: 60 * 60 * 24,
  };
  return Math.floor(Date.now() / 1000) + value * multipliers[unit!]!;
}

export async function sign(payload: any, expiration = '30d') {
  const now = Math.floor(Date.now() / 1000);
  const exp = parseExpiration(expiration);
  const jti = crypto.randomUUID();
  const data = { ...payload, exp, iat: now, jti };
  return jwtSign(data, signingKey());
}

export async function verify(token: string): Promise<any> {
  return jwtVerify(token, signingKey(), 'HS256');
}
