const KEY_PREFIX = 'pdf2html' as const

export type IdempotencyKey = string & { readonly __brand: 'IdempotencyKey' }

function segment(value: string, name: string): string {
  if (typeof value !== 'string' || value.length === 0) throw new TypeError(`${name} is required`)
  return encodeURIComponent(value)
}

function key(namespace: string, parts: readonly [string, ...string[]]): IdempotencyKey {
  return [KEY_PREFIX, namespace, ...parts.map((part, index) => segment(part, `part ${index + 1}`))].join(':') as IdempotencyKey
}

export function purchaseIdempotencyKey(userId: string, purchaseIntentId: string): IdempotencyKey {
  return key('purchase', [userId, purchaseIntentId])
}

export function providerEventIdempotencyKey(provider: string, eventId: string): IdempotencyKey {
  return key('event', [provider, eventId])
}

export function grantIdempotencyKey(provider: string, paymentId: string): IdempotencyKey {
  return key('grant', [provider, paymentId])
}

export function reversalIdempotencyKey(
  provider: string,
  reversalKind: 'refund' | 'dispute' | 'chargeback',
  reversalObjectId: string,
): IdempotencyKey {
  return key('reversal', [provider, reversalKind, reversalObjectId])
}

export function submissionIdempotencyKey(userId: string, clientSubmissionId: string): IdempotencyKey {
  return key('submission', [userId, clientSubmissionId])
}

export function debitIdempotencyKey(conversionId: string): IdempotencyKey {
  return key('debit', [conversionId])
}

export function compensationIdempotencyKey(conversionId: string): IdempotencyKey {
  return key('compensation', [conversionId])
}

export function operatorAdjustmentIdempotencyKey(adjustmentId: string): IdempotencyKey {
  return key('operator-adjustment', [adjustmentId])
}
