/**
 * Tests for file upload API route
 *
 * @vitest-environment node
 */
import {
  authMockFns,
  hybridAuthMockFns,
  permissionsMock,
  permissionsMockFns,
  storageServiceMock,
  storageServiceMockFns,
} from '@sim/testing'
import { NextRequest } from 'next/server'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

const mocks = vi.hoisted(() => {
  const mockVerifyFileAccess = vi.fn()
  const mockVerifyWorkspaceFileAccess = vi.fn()
  const mockVerifyKBFileAccess = vi.fn()
  const mockVerifyCopilotFileAccess = vi.fn()
  const mockUploadWorkspaceFile = vi.fn()
  const mockGetStorageProvider = vi.fn()
  const mockIsUsingCloudStorage = vi.fn()
  const mockUploadFile = vi.fn()
  const mockUploadExecutionFile = vi.fn()
  const mockCheckStorageQuota = vi.fn()

  return {
    mockVerifyFileAccess,
    mockVerifyWorkspaceFileAccess,
    mockVerifyKBFileAccess,
    mockVerifyCopilotFileAccess,
    mockUploadWorkspaceFile,
    mockGetStorageProvider,
    mockIsUsingCloudStorage,
    mockUploadFile,
    mockUploadExecutionFile,
    mockCheckStorageQuota,
  }
})

vi.mock('drizzle-orm', () => ({
  and: vi.fn((...conditions: unknown[]) => ({ conditions, type: 'and' })),
  eq: vi.fn((field: unknown, value: unknown) => ({ field, value, type: 'eq' })),
  or: vi.fn((...conditions: unknown[]) => ({ type: 'or', conditions })),
  gte: vi.fn((field: unknown, value: unknown) => ({ type: 'gte', field, value })),
  lte: vi.fn((field: unknown, value: unknown) => ({ type: 'lte', field, value })),
  gt: vi.fn((field: unknown, value: unknown) => ({ type: 'gt', field, value })),
  lt: vi.fn((field: unknown, value: unknown) => ({ type: 'lt', field, value })),
  ne: vi.fn((field: unknown, value: unknown) => ({ type: 'ne', field, value })),
  asc: vi.fn((field: unknown) => ({ field, type: 'asc' })),
  desc: vi.fn((field: unknown) => ({ field, type: 'desc' })),
  isNull: vi.fn((field: unknown) => ({ field, type: 'isNull' })),
  isNotNull: vi.fn((field: unknown) => ({ field, type: 'isNotNull' })),
  inArray: vi.fn((field: unknown, values: unknown) => ({ field, values, type: 'inArray' })),
  notInArray: vi.fn((field: unknown, values: unknown) => ({ field, values, type: 'notInArray' })),
  like: vi.fn((field: unknown, value: unknown) => ({ field, value, type: 'like' })),
  ilike: vi.fn((field: unknown, value: unknown) => ({ field, value, type: 'ilike' })),
  count: vi.fn((field: unknown) => ({ field, type: 'count' })),
  sum: vi.fn((field: unknown) => ({ field, type: 'sum' })),
  avg: vi.fn((field: unknown) => ({ field, type: 'avg' })),
  min: vi.fn((field: unknown) => ({ field, type: 'min' })),
  max: vi.fn((field: unknown) => ({ field, type: 'max' })),
  sql: vi.fn((strings: unknown, ...values: unknown[]) => ({ type: 'sql', sql: strings, values })),
}))

vi.mock('@sim/utils/id', () => ({
  generateId: vi.fn(() => 'test-uuid'),
  generateShortId: vi.fn(() => 'mock-short-id'),
  isValidUuid: vi.fn((v: string) =>
    /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)
  ),
}))

vi.mock('@/app/api/files/authorization', () => ({
  verifyFileAccess: mocks.mockVerifyFileAccess,
  verifyWorkspaceFileAccess: mocks.mockVerifyWorkspaceFileAccess,
  verifyKBFileAccess: mocks.mockVerifyKBFileAccess,
  verifyCopilotFileAccess: mocks.mockVerifyCopilotFileAccess,
}))

vi.mock('@/lib/workspaces/permissions/utils', () => permissionsMock)

vi.mock('@/lib/uploads/contexts/workspace', () => ({
  uploadWorkspaceFile: mocks.mockUploadWorkspaceFile,
}))

vi.mock('@/lib/uploads/contexts/execution', () => ({
  uploadExecutionFile: mocks.mockUploadExecutionFile,
}))

vi.mock('@/lib/uploads', () => ({
  getStorageProvider: mocks.mockGetStorageProvider,
  isUsingCloudStorage: mocks.mockIsUsingCloudStorage,
  uploadFile: mocks.mockUploadFile,
}))

vi.mock('@/lib/uploads/core/storage-service', () => storageServiceMock)

vi.mock('@/lib/uploads/shared/types', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@/lib/uploads/shared/types')>()
  return {
    ...actual,
    MAX_WORKSPACE_FORMDATA_FILE_SIZE: 1024,
  }
})

vi.mock('@/lib/uploads/setup.server', () => ({
  UPLOAD_DIR_SERVER: '/tmp/test-uploads',
}))

vi.mock('@/lib/billing/storage', () => ({
  checkStorageQuota: mocks.mockCheckStorageQuota,
}))

import { uploadWorkspaceFile } from '@/lib/uploads/contexts/workspace'
import { POST } from '@/app/api/files/upload/route'

/**
 * Configure mocks for authenticated file upload tests
 */
function setupFileApiMocks(
  options: {
    authenticated?: boolean
    storageProvider?: 's3' | 'blob' | 'local'
    cloudEnabled?: boolean
  } = {}
) {
  const { authenticated = true, storageProvider = 's3', cloudEnabled = true } = options

  vi.stubGlobal('crypto', {
    randomUUID: vi.fn().mockReturnValue('mock-uuid-1234-5678'),
  })

  if (authenticated) {
    authMockFns.mockGetSession.mockResolvedValue({ user: { id: 'test-user-id' } })
  } else {
    authMockFns.mockGetSession.mockResolvedValue(null)
  }

  hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValue({
    success: authenticated,
    userId: authenticated ? 'test-user-id' : undefined,
    error: authenticated ? undefined : 'Unauthorized',
  })

  mocks.mockVerifyFileAccess.mockResolvedValue(true)
  mocks.mockVerifyWorkspaceFileAccess.mockResolvedValue(true)
  mocks.mockVerifyKBFileAccess.mockResolvedValue(true)
  mocks.mockVerifyCopilotFileAccess.mockResolvedValue(true)

  permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('admin')

  mocks.mockUploadWorkspaceFile.mockResolvedValue({
    id: 'test-file-id',
    name: 'test.txt',
    url: '/api/files/serve/workspace/test-workspace-id/test-file.txt',
    size: 100,
    type: 'text/plain',
    key: 'workspace/test-workspace-id/1234567890-test.txt',
    uploadedAt: new Date().toISOString(),
    expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
  })

  mocks.mockUploadExecutionFile.mockResolvedValue({
    id: 'test-execution-file-id',
    name: 'test.txt',
    url: '/api/files/serve/execution/test-workspace-id/test-file.txt',
    size: 100,
    type: 'text/plain',
    key: 'execution/test-workspace-id/1234567890-test.txt',
    uploadedAt: new Date().toISOString(),
    expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
  })

  mocks.mockGetStorageProvider.mockReturnValue(storageProvider)
  mocks.mockIsUsingCloudStorage.mockReturnValue(cloudEnabled)
  mocks.mockUploadFile.mockResolvedValue({
    path: '/api/files/serve/test-key.txt',
    key: 'test-key.txt',
    name: 'test.txt',
    size: 100,
    type: 'text/plain',
  })

  storageServiceMockFns.mockHasCloudStorage.mockReturnValue(cloudEnabled)
  storageServiceMockFns.mockUploadFile.mockResolvedValue({
    key: 'test-key',
    path: '/test/path',
  })

  mocks.mockCheckStorageQuota.mockResolvedValue({
    allowed: true,
    currentUsage: 0,
    limit: Number.MAX_SAFE_INTEGER,
  })
}

describe('File Upload API Route', () => {
  const createMockFormData = (files: File[], context = 'workspace'): FormData => {
    const formData = new FormData()
    formData.append('context', context)
    formData.append('workspaceId', 'test-workspace-id')
    files.forEach((file) => {
      formData.append('file', file)
    })
    return formData
  }

  const createMockFile = (
    name = 'test.txt',
    type = 'text/plain',
    content = 'test content'
  ): File => {
    return new File([content], name, { type })
  }

  const createUploadRequest = (formData: FormData): NextRequest =>
    new NextRequest('http://localhost:3000/api/files/upload', {
      method: 'POST',
      headers: { 'content-length': '1024' },
      body: formData,
    })

  beforeEach(() => {
    vi.clearAllMocks()
  })

  afterEach(() => {
    vi.clearAllMocks()
  })

  it('should upload a file to local storage', async () => {
    setupFileApiMocks({
      cloudEnabled: false,
      storageProvider: 'local',
    })

    const mockFile = createMockFile()
    const formData = createMockFormData([mockFile])

    const req = createUploadRequest(formData)

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBe(200)
    expect(data).toHaveProperty('url')
    expect(data.url).toMatch(/\/api\/files\/serve\/.*\.txt$/)
    expect(data).toHaveProperty('name', 'test.txt')
    expect(data).toHaveProperty('size')
    expect(data).toHaveProperty('type', 'text/plain')
    expect(data).toHaveProperty('key')

    expect(uploadWorkspaceFile).toHaveBeenCalled()
  })

  it('should accept chunked multipart uploads without a content-length header', async () => {
    setupFileApiMocks({
      cloudEnabled: false,
      storageProvider: 'local',
    })

    const formData = createMockFormData([createMockFile()])
    const req = new NextRequest('http://localhost:3000/api/files/upload', {
      method: 'POST',
      body: formData,
    })

    expect(req.headers.get('content-length')).toBeNull()

    const response = await POST(req)

    expect(response.status).toBe(200)
    expect(uploadWorkspaceFile).toHaveBeenCalled()
  })

  it('should upload a file to S3 when in S3 mode', async () => {
    setupFileApiMocks({
      cloudEnabled: true,
      storageProvider: 's3',
    })

    const mockFile = createMockFile()
    const formData = createMockFormData([mockFile])

    const req = createUploadRequest(formData)

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBe(200)
    expect(data).toHaveProperty('url')
    expect(data.url).toContain('/api/files/serve/')
    expect(data).toHaveProperty('name', 'test.txt')
    expect(data).toHaveProperty('size')
    expect(data).toHaveProperty('type', 'text/plain')
    expect(data).toHaveProperty('key')

    expect(uploadWorkspaceFile).toHaveBeenCalled()
  })

  it('should handle multiple file uploads', async () => {
    setupFileApiMocks({
      cloudEnabled: false,
      storageProvider: 'local',
    })

    const mockFile1 = createMockFile('file1.txt', 'text/plain')
    const mockFile2 = createMockFile('file2.txt', 'text/plain')
    const formData = createMockFormData([mockFile1, mockFile2])

    const req = createUploadRequest(formData)

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBeGreaterThanOrEqual(200)
    expect(response.status).toBeLessThan(600)
    expect(data).toBeDefined()
  })

  it('rejects oversized workspace uploads before materializing file contents', async () => {
    setupFileApiMocks({
      cloudEnabled: false,
      storageProvider: 'local',
    })

    const mockFile = createMockFile('large.txt', 'text/plain', 'x'.repeat(1025))
    const arrayBufferSpy = vi.spyOn(mockFile, 'arrayBuffer')
    const formData = {
      getAll: (name: string) => (name === 'file' ? [mockFile] : []),
      get: (name: string) => {
        if (name === 'context') return 'workspace'
        if (name === 'workspaceId') return 'test-workspace-id'
        return null
      },
    } as unknown as FormData

    const req = {
      formData: async () => formData,
    } as unknown as NextRequest

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBe(413)
    expect(data.error).toBe('PayloadSizeLimitError')
    expect(data.message).toContain('File exceeds the server upload limit')
    expect(data.message).toContain('Use direct upload for larger workspace files')
    expect(arrayBufferSpy).not.toHaveBeenCalled()
    expect(uploadWorkspaceFile).not.toHaveBeenCalled()
  })

  it('should handle missing files', async () => {
    setupFileApiMocks()

    const formData = new FormData()

    const req = createUploadRequest(formData)

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBe(400)
    expect(data).toHaveProperty('error', 'InvalidRequestError')
    expect(data).toHaveProperty('message', 'No files provided')
  })

  it('should handle S3 upload errors', async () => {
    setupFileApiMocks({
      cloudEnabled: true,
      storageProvider: 's3',
    })

    mocks.mockUploadWorkspaceFile.mockRejectedValue(new Error('Storage limit exceeded'))

    const mockFile = createMockFile()
    const formData = createMockFormData([mockFile])

    const req = createUploadRequest(formData)

    const response = await POST(req)
    const data = await response.json()

    expect(response.status).toBe(413)
    expect(data).toHaveProperty('error')
    expect(typeof data.error).toBe('string')
  })
})

describe('File Upload Security Tests', () => {
  beforeEach(() => {
    vi.clearAllMocks()

    authMockFns.mockGetSession.mockResolvedValue({
      user: { id: 'test-user-id' },
    })

    storageServiceMockFns.mockHasCloudStorage.mockReturnValue(false)
    storageServiceMockFns.mockUploadFile.mockResolvedValue({
      key: 'test-key',
      path: '/test/path',
    })
    mocks.mockIsUsingCloudStorage.mockReturnValue(false)
  })

  afterEach(() => {
    vi.clearAllMocks()
  })

  describe('File Extension Validation', () => {
    beforeEach(() => {
      setupFileApiMocks({
        cloudEnabled: false,
        storageProvider: 'local',
      })
    })

    it('should accept allowed file types', async () => {
      const allowedTypes = [
        'pdf',
        'doc',
        'docx',
        'txt',
        'md',
        'png',
        'jpg',
        'jpeg',
        'gif',
        'csv',
        'xlsx',
        'xls',
      ]

      for (const ext of allowedTypes) {
        const formData = new FormData()
        const file = new File(['test content'], `test.${ext}`, { type: 'application/octet-stream' })
        formData.append('file', file)
        formData.append('context', 'workspace')
        formData.append('workspaceId', 'test-workspace-id')

        const req = new Request('http://localhost/api/files/upload', {
          method: 'POST',
          headers: { 'content-length': '1024' },
          body: formData,
        })

        const response = await POST(req as unknown as NextRequest)

        expect(response.status).toBe(200)
      }
    })

    it('should accept HTML files (supported document type)', async () => {
      const formData = new FormData()
      const htmlContent = '<h1>Hello World</h1>'
      const file = new File([htmlContent], 'document.html', { type: 'text/html' })
      formData.append('file', file)
      formData.append('context', 'workspace')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(200)
    })

    it('should accept SVG files (supported image type)', async () => {
      const formData = new FormData()
      const svgContent =
        '<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100"/></svg>'
      const file = new File([svgContent], 'image.svg', { type: 'image/svg+xml' })
      formData.append('file', file)
      formData.append('context', 'workspace')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(200)
    })

    it('should reject unsupported file types', async () => {
      const formData = new FormData()
      const content = 'binary data'
      const file = new File([content], 'archive.exe', { type: 'application/octet-stream' })
      formData.append('file', file)
      formData.append('context', 'workspace')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(400)
      const data = await response.json()
      expect(data.message).toContain("File type 'exe' is not allowed")
    })

    it('should reject files without extensions', async () => {
      const formData = new FormData()
      const file = new File(['test content'], 'noextension', { type: 'application/octet-stream' })
      formData.append('file', file)
      formData.append('context', 'workspace')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(400)
      const data = await response.json()
      expect(data.message).toContain("File type 'noextension' is not allowed")
    })

    it('should handle multiple files with mixed valid/invalid types', async () => {
      const formData = new FormData()

      const validFile = new File(['valid content'], 'valid.pdf', { type: 'application/pdf' })
      formData.append('file', validFile)

      const invalidFile = new File(['binary content'], 'malicious.exe', {
        type: 'application/x-msdownload',
      })
      formData.append('file', invalidFile)
      formData.append('context', 'workspace')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(400)
      const data = await response.json()
      expect(data.message).toContain("File type 'exe' is not allowed")
    })
  })

  describe('Execution Context Permission Gate', () => {
    const createExecutionFormData = (
      file: File,
      workspaceId: string | null = 'test-workspace-id'
    ) => {
      const formData = new FormData()
      formData.append('file', file)
      formData.append('context', 'execution')
      formData.append('workflowId', 'test-workflow-id')
      formData.append('executionId', 'test-execution-id')
      if (workspaceId !== null) formData.append('workspaceId', workspaceId)
      return formData
    }

    const postExecutionUpload = async (workspaceId: string | null = 'test-workspace-id') => {
      const file = new File(['test content'], 'test.pdf', { type: 'application/pdf' })
      const formData = createExecutionFormData(file, workspaceId)

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      return POST(req as unknown as NextRequest)
    }

    beforeEach(() => {
      setupFileApiMocks({
        cloudEnabled: false,
        storageProvider: 'local',
      })
    })

    it('rejects execution uploads without workspaceId', async () => {
      const response = await postExecutionUpload(null)

      expect(response.status).toBe(400)
      const data = await response.json()
      expect(data.message).toContain('workflowId, executionId, and workspaceId')
      expect(mocks.mockUploadExecutionFile).not.toHaveBeenCalled()
    })

    it('rejects execution uploads for a read-only workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('read')

      const response = await postExecutionUpload()

      expect(response.status).toBe(403)
      const data = await response.json()
      expect(data.error).toBe('Write or Admin access required for execution uploads')
      expect(mocks.mockUploadExecutionFile).not.toHaveBeenCalled()
    })

    it('rejects execution uploads for a member with no workspace permission', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue(null)

      const response = await postExecutionUpload()

      expect(response.status).toBe(403)
      expect(mocks.mockUploadExecutionFile).not.toHaveBeenCalled()
    })

    it('allows execution uploads for a write-permission workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('write')

      const response = await postExecutionUpload()

      expect(response.status).toBe(200)
      expect(mocks.mockUploadExecutionFile).toHaveBeenCalledWith(
        {
          workspaceId: 'test-workspace-id',
          workflowId: 'test-workflow-id',
          executionId: 'test-execution-id',
        },
        expect.anything(),
        'test.pdf',
        'application/pdf',
        'test-user-id'
      )
    })

    it('allows execution uploads for an admin-permission workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('admin')

      const response = await postExecutionUpload()

      expect(response.status).toBe(200)
      expect(mocks.mockUploadExecutionFile).toHaveBeenCalled()
    })
  })

  describe('Mothership Context Permission Gate', () => {
    const postMothershipUpload = async (workspaceId: string | null = 'test-workspace-id') => {
      const formData = new FormData()
      const file = new File(['test content'], 'test.pdf', { type: 'application/pdf' })
      formData.append('file', file)
      formData.append('context', 'mothership')
      if (workspaceId !== null) formData.append('workspaceId', workspaceId)

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      return POST(req as unknown as NextRequest)
    }

    beforeEach(() => {
      setupFileApiMocks({
        cloudEnabled: false,
        storageProvider: 'local',
      })
    })

    it('rejects mothership uploads without workspaceId', async () => {
      const response = await postMothershipUpload(null)

      expect(response.status).toBe(400)
      const data = await response.json()
      expect(data.message).toContain('workspaceId')
      expect(storageServiceMockFns.mockUploadFile).not.toHaveBeenCalled()
    })

    it('rejects mothership uploads for a workspace the caller does not belong to', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue(null)

      const response = await postMothershipUpload()

      expect(response.status).toBe(403)
      const data = await response.json()
      expect(data.error).toBe('Write or Admin access required for mothership uploads')
      expect(storageServiceMockFns.mockUploadFile).not.toHaveBeenCalled()
    })

    it('rejects mothership uploads for a read-only workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('read')

      const response = await postMothershipUpload()

      expect(response.status).toBe(403)
      expect(storageServiceMockFns.mockUploadFile).not.toHaveBeenCalled()
    })

    it('rejects mothership uploads over the caller storage quota', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('write')
      mocks.mockCheckStorageQuota.mockResolvedValue({
        allowed: false,
        currentUsage: 100,
        limit: 100,
        error: 'Storage limit exceeded. Used: 0.00GB, Limit: 0GB',
      })

      const response = await postMothershipUpload()

      expect(response.status).toBe(413)
      const data = await response.json()
      expect(data.error).toContain('Storage limit exceeded')
      expect(storageServiceMockFns.mockUploadFile).not.toHaveBeenCalled()
    })

    it('allows mothership uploads for a write-permission workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('write')

      const response = await postMothershipUpload()

      expect(response.status).toBe(200)
      expect(permissionsMockFns.mockGetUserEntityPermissions).toHaveBeenCalledWith(
        'test-user-id',
        'workspace',
        'test-workspace-id'
      )
      expect(storageServiceMockFns.mockUploadFile).toHaveBeenCalled()
    })

    it('allows mothership uploads for an admin-permission workspace member', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('admin')

      const response = await postMothershipUpload()

      expect(response.status).toBe(200)
      expect(storageServiceMockFns.mockUploadFile).toHaveBeenCalled()
    })

    it('checks quota once against the combined size of a multi-file batch', async () => {
      permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue('write')

      const formData = new FormData()
      const fileA = new File(['a'.repeat(10)], 'a.pdf', { type: 'application/pdf' })
      const fileB = new File(['b'.repeat(20)], 'b.pdf', { type: 'application/pdf' })
      formData.append('file', fileA)
      formData.append('file', fileB)
      formData.append('context', 'mothership')
      formData.append('workspaceId', 'test-workspace-id')

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(200)
      expect(mocks.mockCheckStorageQuota).toHaveBeenCalledTimes(1)
      expect(mocks.mockCheckStorageQuota).toHaveBeenCalledWith('test-user-id', 30)
      expect(permissionsMockFns.mockGetUserEntityPermissions).toHaveBeenCalledTimes(1)
    })
  })

  describe('Authentication Requirements', () => {
    it('should reject uploads without authentication', async () => {
      authMockFns.mockGetSession.mockResolvedValue(null)

      const formData = new FormData()
      const file = new File(['test content'], 'test.pdf', { type: 'application/pdf' })
      formData.append('file', file)

      const req = new Request('http://localhost/api/files/upload', {
        method: 'POST',
        headers: { 'content-length': '1024' },
        body: formData,
      })

      const response = await POST(req as unknown as NextRequest)

      expect(response.status).toBe(401)
      const data = await response.json()
      expect(data.error).toBe('Unauthorized')
    })
  })
})
