import crypto from 'node:crypto'

export type GitHubWebhookAction =
  | { type: 'issue_opened'; issueNumber: number; url: string }
  | { type: 'issue_comment'; issueNumber: number; body: string }
  | { type: 'pull_request_opened'; pullNumber: number; url: string }
  | { type: 'check_completed'; conclusion: string | null; url: string | null }
  | { type: 'workflow_completed'; conclusion: string | null; url: string | null }
  | { type: 'projects_v2_event'; action: string }
  | { type: 'ignored'; reason: string }

export function verifyGitHubWebhookSignature(
  body: string | Buffer,
  signatureHeader: string | undefined,
  secret: string,
): boolean {
  if (!signatureHeader || !signatureHeader.startsWith('sha256=')) return false

  const expected = `sha256=${crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex')}`

  return timingSafeEqual(expected, signatureHeader)
}

export function dispatchGitHubWebhook(event: string, payload: any): GitHubWebhookAction {
  const action = String(payload?.action ?? '')

  if (event === 'issues' && action === 'opened') {
    return {
      type: 'issue_opened',
      issueNumber: Number(payload.issue?.number),
      url: String(payload.issue?.html_url ?? ''),
    }
  }

  if (event === 'issue_comment') {
    return {
      type: 'issue_comment',
      issueNumber: Number(payload.issue?.number),
      body: String(payload.comment?.body ?? ''),
    }
  }

  if (event === 'pull_request' && action === 'opened') {
    return {
      type: 'pull_request_opened',
      pullNumber: Number(payload.pull_request?.number),
      url: String(payload.pull_request?.html_url ?? ''),
    }
  }

  if (event === 'check_suite' && action === 'completed') {
    return {
      type: 'check_completed',
      conclusion: payload.check_suite?.conclusion ?? null,
      url: payload.check_suite?.html_url ?? null,
    }
  }

  if (event === 'workflow_run' && action === 'completed') {
    return {
      type: 'workflow_completed',
      conclusion: payload.workflow_run?.conclusion ?? null,
      url: payload.workflow_run?.html_url ?? null,
    }
  }

  if (event === 'projects_v2' || event === 'projects_v2_item' || event === 'projects_v2_status_update') {
    return { type: 'projects_v2_event', action }
  }

  return { type: 'ignored', reason: `${event}:${action || 'no-action'}` }
}

function timingSafeEqual(left: string, right: string): boolean {
  const a = Buffer.from(left)
  const b = Buffer.from(right)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
