import { vi } from 'vitest'

// Type for mock response configuration
export interface MockResponseConfig {
  status?: number
  ok?: boolean
  json?: unknown
  text?: string
  headers?: Record<string, string>
}

// Create a mock fetch response
export function createMockResponse(config: MockResponseConfig = {}): Response {
  const {
    status = 200,
    ok = status >= 200 && status < 300,
    json = {},
    text = '',
    headers = {},
  } = config

  return {
    ok,
    status,
    statusText: ok ? 'OK' : 'Error',
    headers: new Headers(headers),
    json: vi.fn().mockResolvedValue(json),
    text: vi.fn().mockResolvedValue(text || JSON.stringify(json)),
    blob: vi.fn().mockResolvedValue(new Blob()),
    arrayBuffer: vi.fn().mockResolvedValue(new ArrayBuffer(0)),
    formData: vi.fn().mockResolvedValue(new FormData()),
    clone: vi.fn(),
    body: null,
    bodyUsed: false,
    redirected: false,
    type: 'basic' as ResponseType,
    url: '',
  } as unknown as Response
}

// Mock fetch function
export const mockFetch = vi.fn()

// Setup fetch to return a specific response
export function setMockFetchResponse(config: MockResponseConfig) {
  mockFetch.mockResolvedValue(createMockResponse(config))
}

// Setup fetch to return different responses based on URL
export function setMockFetchResponses(responses: Record<string, MockResponseConfig>) {
  mockFetch.mockImplementation((url: string) => {
    const config = responses[url] || { status: 404, ok: false }
    return Promise.resolve(createMockResponse(config))
  })
}

// Setup fetch to throw an error
export function setMockFetchError(error: Error) {
  mockFetch.mockRejectedValue(error)
}

// Reset fetch mock
export function resetFetchMock() {
  mockFetch.mockReset()
  mockFetch.mockResolvedValue(createMockResponse())
}

// Replace global fetch
vi.stubGlobal('fetch', mockFetch)
