import crypto from 'node:crypto'
import { describe, expect, it } from 'vitest'

import { verifyPaddleWebhookSignature } from '../paddle-webhook'

function buildSignatureHeader({
  rawBody,
  secretKey,
  timestamp,
}: {
  rawBody: string
  secretKey: string
  timestamp: string
}) {
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(`${timestamp}:${rawBody}`)
    .digest('hex')

  return `ts=${timestamp};h1=${signature}`
}

describe('verifyPaddleWebhookSignature', () => {
  it('accepts a valid signature built from the raw body', () => {
    const rawBody = JSON.stringify({ event_id: 'evt_123', event_type: 'transaction.completed' })
    const timestamp = '1719012345'
    const secretKey = 'pdl_ntfset_test_secret'

    const result = verifyPaddleWebhookSignature({
      rawBody,
      signatureHeader: buildSignatureHeader({ rawBody, secretKey, timestamp }),
      secretKey,
      toleranceMs: 5_000,
      now: () => Number(timestamp) * 1_000 + 1_000,
    })

    expect(result).toEqual({ ok: true, timestamp })
  })

  it('rejects missing or malformed headers', () => {
    const rawBody = '{}'
    const secretKey = 'pdl_ntfset_test_secret'

    expect(verifyPaddleWebhookSignature({
      rawBody,
      signatureHeader: '',
      secretKey,
    })).toEqual({ ok: false, error: 'missing_signature' })

    expect(verifyPaddleWebhookSignature({
      rawBody,
      signatureHeader: 'ts=1719012345',
      secretKey,
    })).toEqual({ ok: false, error: 'invalid_signature_header' })
  })

  it('rejects signatures that are outside the tolerance window', () => {
    const rawBody = '{}'
    const timestamp = '1719012345'
    const secretKey = 'pdl_ntfset_test_secret'

    const result = verifyPaddleWebhookSignature({
      rawBody,
      signatureHeader: buildSignatureHeader({ rawBody, secretKey, timestamp }),
      secretKey,
      toleranceMs: 5_000,
      now: () => Number(timestamp) * 1_000 + 6_000,
    })

    expect(result).toEqual({ ok: false, error: 'expired_signature' })
  })

  it('rejects mismatched signatures', () => {
    const rawBody = '{}'
    const secretKey = 'pdl_ntfset_test_secret'

    const result = verifyPaddleWebhookSignature({
      rawBody,
      signatureHeader: 'ts=1719012345;h1=deadbeef',
      secretKey,
      toleranceMs: 5_000,
      now: () => 1719012345_000 + 1_000,
    })

    expect(result).toEqual({ ok: false, error: 'invalid_signature' })
  })

  it('fails closed when the secret key is missing', () => {
    const result = verifyPaddleWebhookSignature({
      rawBody: '{}',
      signatureHeader: 'ts=1719012345;h1=deadbeef',
      secretKey: '',
    })

    expect(result).toEqual({ ok: false, error: 'missing_secret' })
  })
})
