'use strict'

const { test } = require('node:test')
const { Cache } = require('../../lib/web/cache/cache')
const { caches, Response } = require('../../')

test('constructor', (t) => {
  t.assert.throws(() => new Cache(null), {
    name: 'TypeError',
    message: 'TypeError: Illegal constructor'
  })
})

// https://github.com/nodejs/undici/issues/4710
test('cache.match should work after garbage collection', async (t) => {
  const cache = await caches.open('test-gc-cache')

  t.after(async () => {
    await caches.delete('test-gc-cache')
  })

  const url = 'https://example.com/test-gc'
  const testData = { answer: 42 }

  await cache.put(url, Response.json(testData))

  // Call match multiple times with GC pressure between calls
  // The bug manifests when the temporary Response object from fromInnerResponse()
  // is garbage collected, which triggers the FinalizationRegistry to cancel
  // the cached stream.
  for (let i = 0; i < 20; i++) {
    // Create significant memory pressure to trigger GC
    // eslint-disable-next-line no-unused-vars
    const garbage = Array.from({ length: 30000 }, () => ({ value: Math.random() }))

    // Force GC if available (run with --expose-gc)
    if (global.gc) {
      global.gc()
    }

    // Delay to allow FinalizationRegistry callbacks to run
    // The bug requires time for the GC to collect the temporary Response
    // and for the finalization callback to cancel the stream
    await new Promise((resolve) => setTimeout(resolve, 10))

    // This should not throw "Body has already been consumed"
    const match = await cache.match(url)
    t.assert.ok(match, `Iteration ${i}: match should return a response`)

    const result = await match.json()
    t.assert.deepStrictEqual(result, testData, `Iteration ${i}: response body should match`)
  }
})
