import { safeCompare } from '@sim/security/compare'
import { hmacSha256Base64 } from '@sim/security/hmac'
import { env } from '@/lib/core/config/env'
import type { StorageContext } from '@/lib/uploads/shared/types'

export interface UploadTokenPayload {
  uploadId: string
  key: string
  userId: string
  workspaceId: string
  context: StorageContext
  /** Original file name, carried so the completion handler can record ownership metadata. */
  fileName?: string
  /** File MIME type, carried for ownership metadata at completion. */
  contentType?: string
  /** File size in bytes, carried for ownership metadata at completion. */
  fileSize?: number
}

interface SignedPayload extends UploadTokenPayload {
  exp: number
  v: 1
}

const toBase64Url = (input: string): string => Buffer.from(input, 'utf8').toString('base64url')

const fromBase64Url = (input: string): string => Buffer.from(input, 'base64url').toString('utf8')

const sign = (payload: string): string => hmacSha256Base64(payload, env.INTERNAL_API_SECRET)

/**
 * Sign an upload session token binding (uploadId, key, userId, workspaceId, context).
 * Used to prevent IDOR on multipart upload follow-up calls (get-part-urls, complete, abort).
 */
export function signUploadToken(payload: UploadTokenPayload, expiresInSeconds = 60 * 60): string {
  const signed: SignedPayload = {
    ...payload,
    exp: Math.floor(Date.now() / 1000) + expiresInSeconds,
    v: 1,
  }
  const encoded = toBase64Url(JSON.stringify(signed))
  return `${encoded}.${sign(encoded)}`
}

export type UploadTokenVerification =
  | { valid: true; payload: UploadTokenPayload }
  | { valid: false }

export function verifyUploadToken(token: string): UploadTokenVerification {
  if (typeof token !== 'string') {
    return { valid: false }
  }
  const parts = token.split('.')
  if (parts.length !== 2) return { valid: false }
  const [encoded, signature] = parts
  if (!encoded || !signature) return { valid: false }

  const expected = sign(encoded)
  if (!safeCompare(signature, expected)) {
    return { valid: false }
  }

  let parsed: SignedPayload
  try {
    parsed = JSON.parse(fromBase64Url(encoded)) as SignedPayload
  } catch {
    return { valid: false }
  }

  if (
    parsed.v !== 1 ||
    typeof parsed.exp !== 'number' ||
    parsed.exp < Math.floor(Date.now() / 1000) ||
    typeof parsed.uploadId !== 'string' ||
    typeof parsed.key !== 'string' ||
    typeof parsed.userId !== 'string' ||
    typeof parsed.workspaceId !== 'string' ||
    typeof parsed.context !== 'string'
  ) {
    return { valid: false }
  }

  return {
    valid: true,
    payload: {
      uploadId: parsed.uploadId,
      key: parsed.key,
      userId: parsed.userId,
      workspaceId: parsed.workspaceId,
      context: parsed.context as StorageContext,
      ...(typeof parsed.fileName === 'string' ? { fileName: parsed.fileName } : {}),
      ...(typeof parsed.contentType === 'string' ? { contentType: parsed.contentType } : {}),
      ...(typeof parsed.fileSize === 'number' ? { fileSize: parsed.fileSize } : {}),
    },
  }
}
