import {createHmac,timingSafeEqual} from 'node:crypto'

// Pass the original request bytes, before any JSON body parser modifies them.
// Store the returned event.id in a durable UNIQUE column together with your work.
// A duplicate valid event should receive a 2xx response without repeating that work.
export function verifyLumyrenWebhook({rawBody,headers,secret,now=Date.now()}) {
  if(!Buffer.isBuffer(rawBody)||rawBody.length>2048)throw new Error('Invalid webhook body')
  if(typeof secret!=='string'||!/^whsec_[A-Za-z0-9_-]{43}$/.test(secret))throw new Error('Missing webhook secret')
  const header=name=>typeof headers?.get==='function'?headers.get(name):headers?.[name]
  const id=header('webhook-id'),timestamp=header('webhook-timestamp'),signature=header('webhook-signature')
  if(typeof id!=='string'||!/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(id)
    ||typeof timestamp!=='string'||!/^\d{10,12}$/.test(timestamp)
    ||typeof signature!=='string'||!/^v1=[a-f0-9]{64}$/.test(signature))throw new Error('Invalid webhook headers')
  if(!Number.isFinite(now)||Math.abs(Math.floor(now/1000)-Number(timestamp))>300)throw new Error('Webhook timestamp outside five-minute window')
  const expected=createHmac('sha256',secret).update(id+'.'+timestamp+'.').update(rawBody).digest()
  if(!timingSafeEqual(expected,Buffer.from(signature.slice(3),'hex')))throw new Error('Invalid webhook signature')
  const event=JSON.parse(rawBody.toString('utf8'))
  if(event?.id!==id||!['job.succeeded','job.failed','job.cancelled'].includes(event.type))throw new Error('Invalid webhook event')
  return event
}
