import { config } from './config.js'
import { getRedisKey, viteManifestToDeps, viteToOxManifest } from './util.js'
import { logger } from './logger.js'
import * as cache from './cache.js'

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(config.urls.map(async baseUrl => {
    // fetch the manifests
    const result = await fetch(new URL('manifest.json', baseUrl))
    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 function getViteManifests ({ version }) {
  return cache.get(getRedisKey({ version, name: 'viteManifests' }), () => fetchViteManifests())
}

export function getOxManifests ({ version }) {
  return cache.get(getRedisKey({ version, name: 'oxManifests' }), async () => {
    const viteManifests = await getViteManifests({ version })
    return viteToOxManifest(viteManifests)
  })
}

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))
}