import { configMap } from './configMap.js'
import { getRedisKey, viteManifestToDeps, viteToOxManifest } from './util.js'
import { logger } from './logger.js'
import * as cache from './cache.js'
import zlib from 'node:zlib'
import { promisify } from 'node:util'
const brotliCompress = promisify(zlib.brotliCompress)

export async function fetchViteManifests () {
  // vite manifests contains a set of objects with the vite-manifests
  // from the corresponding registered services
  const viteManifests = await Promise.all(configMap.urls.map(async baseUrl => {
    // fetch the manifests
    const result = await fetch(new URL('manifest.json', baseUrl), { cache: 'no-store' })
    if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`)
    try {
      const manifest = await result.json()
      for (const file in manifest) {
        logger.debug(`[Manifest] Retrieved ${file} from ${baseUrl}`)
        manifest[file].meta = manifest[file].meta || {}
        manifest[file].meta.baseUrl = baseUrl
      }
      return manifest
    } catch (err) {
      throw new Error(`Failed to load manifest for url ${result.url}: ${err}`)
    }
  }))

  // combine all manifests by keys. With duplicates, last wins
  return viteManifests.reduce((memo, manifest) => Object.assign(memo, manifest), {})
}

export async function getViteManifests ({ version }) {
  return cache.get(getRedisKey({ version, name: 'viteManifests' }), async () => [await fetchViteManifests()])
}

export function getOxManifests ({ version }) {
  return cache.getFile({ name: 'oxManifests', version }, async () => {
    const headers = { 'content-type': 'application/json; charset=utf-8', 'content-encoding': 'br' }
    const viteManifests = await getViteManifests({ version })
    const oxManifests = await viteToOxManifest(viteManifests)
    const body = await brotliCompress(JSON.stringify(oxManifests))
    return {
      body,
      headers
    }
  })
}

export function getDependencies ({ version }) {
  return cache.get(getRedisKey({ version, name: 'dependencies' }), async () => {
    const viteManifests = await getViteManifests({ version })
    return [viteManifestToDeps(viteManifests)]
  })
}

export async function getCSSDependenciesFor ({ file, version }) {
  const allDependencies = await getDependencies({ version })
  const dependencies = allDependencies[file] || []
  return dependencies.filter(dep => /\.css/i.test(dep))
}