import { randomBytes, createHash } from 'node:crypto';

/**
 * Prefixed, URL-safe identifiers. Prefixes make IDs self-describing in logs and URLs.
 * 20 base32 chars ≈ 100 bits of entropy.
 */
export const ID_PREFIXES = {
  asset: 'rare',
  variant: 'var',
  sale: 'sale',
  listing: 'lst',
  auction: 'auc',
  raw: 'raw',
  source: 'src',
  connector: 'con',
  image: 'img',
  user: 'usr',
  collection: 'col',
  collectionItem: 'ci',
  watchlist: 'wl',
  alert: 'alr',
  apiKey: 'key',
  valuation: 'val',
  job: 'job',
  event: 'evt',
  index: 'idx',
  news: 'news',
  crossListing: 'xl',
  cert: 'cert',
  backfill: 'bf',
} as const;

export type IdKind = keyof typeof ID_PREFIXES;

const ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz'; // Crockford base32, lowercase

function encodeBase32(bytes: Uint8Array, length: number): string {
  let out = '';
  for (let i = 0; i < length; i++) {
    out += ALPHABET[bytes[i]! % 32];
  }
  return out;
}

export function newId(kind: IdKind): string {
  return `${ID_PREFIXES[kind]}_${encodeBase32(randomBytes(20), 20)}`;
}

/** Deterministic id derived from a stable natural key (e.g. source + external id). */
export function deterministicId(kind: IdKind, ...parts: string[]): string {
  const digest = createHash('sha256').update(parts.join(' ')).digest();
  return `${ID_PREFIXES[kind]}_${encodeBase32(digest, 20)}`;
}

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

export function isId(kind: IdKind, value: string): boolean {
  return value.startsWith(`${ID_PREFIXES[kind]}_`) && value.length === ID_PREFIXES[kind].length + 21;
}
