import { createHmac, timingSafeEqual } from 'crypto'

export type MentorUploadPayload = {
  mentorAssignmentId: string
  /**
   * Project the upload belongs to. Bound at token-issue time so the file's
   * project scope can't be tampered with separately from the assignment id.
   * Required (no legacy fallback) — tokens live <1h, so any in-flight tokens
   * issued before this field was added expire on their own.
   */
  projectId: string
  uploaderUserId: string
  fileName: string
  mimeType: string
  size: number
  bucket: string
  objectKey: string
  /** Unix seconds. Token is rejected after this. */
  exp: number
}

function getSecret(): string {
  const s = process.env.NEXTAUTH_SECRET
  if (!s) throw new Error('NEXTAUTH_SECRET is not set; cannot sign mentor upload tokens')
  return s
}

function hmac(payloadB64: string): string {
  return createHmac('sha256', getSecret()).update(payloadB64).digest('hex')
}

export function signMentorUploadToken(payload: MentorUploadPayload): string {
  const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url')
  const sig = hmac(payloadB64)
  return `${payloadB64}.${sig}`
}

export function verifyMentorUploadToken(token: string): MentorUploadPayload {
  const parts = token.split('.')
  if (parts.length !== 2) throw new Error('Invalid mentor upload token: malformed')
  const [payloadB64, sig] = parts
  const expected = hmac(payloadB64)
  const a = Buffer.from(sig, 'hex')
  const b = Buffer.from(expected, 'hex')
  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    throw new Error('Invalid mentor upload token: signature mismatch')
  }
  let payload: MentorUploadPayload
  try {
    payload = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf-8'))
  } catch {
    throw new Error('Invalid mentor upload token: payload not parseable')
  }
  if (typeof payload.exp !== 'number' || payload.exp < Math.floor(Date.now() / 1000)) {
    throw new Error('Invalid mentor upload token: expired')
  }
  if (typeof payload.projectId !== 'string' || payload.projectId.length === 0) {
    throw new Error('Invalid mentor upload token: missing projectId')
  }
  return payload
}
