import { type Configuration } from './content-config'
import { getLayerDirectories } from '@nuxt/kit'
import { join, relative } from 'path'
import { existsSync } from 'fs'
import { readdir } from 'fs/promises'

// this solely exists because in prerender:routes composables or virtual modules are not available yet
export async function getConfig(): Promise<Configuration> {
  const config = getLayerDirectories()
    .map((d) => join(d.app, 'content.config.ts'))
    .find((f) => existsSync(f))

  if (config) {
    const module = await import(config)
    return module.default
  }

  return {}
}

export async function getRoutes(): Promise<Set<string>> {
  async function find(directory: string): Promise<string[]> {
    if (!existsSync(directory)) return []

    const entries = await readdir(directory, { withFileTypes: true, recursive: true })
    return entries
      .filter((e) => e.isFile() && e.name.endsWith('.vue'))
      .map((e) => relative(directory, join(e.parentPath, e.name)))
  }

  const files = await Promise.all(getLayerDirectories().map((d) => find(d.appPages)))
  return new Set(files.flatMap((fs) => fs.map((f) => f.slice(0, -4))))
}

export function getRouteShortcuts(routes: Set<string>): Record<string, string> {
  const shorten = (r: string) => r.replace('[locale]/', '').replace('[variant]/', '')

  const shortcuts = [...routes].map((r) => [shorten(r), r] as [string, string])
  const matches: Record<string, string[]> = {}

  for (const [shortcut, route] of shortcuts) {
    const list = matches[shortcut] ?? []
    list.push(route)
    matches[shortcut] = list
  }

  const unique: Record<string, string> = {}

  for (const [shortcut, routes] of Object.entries(matches)) {
    if (routes.length === 1) {
      unique[shortcut] = routes[0]!
    }
  }

  return unique
}

export async function getExpandedRoutes(config: Configuration): Promise<Set<string>> {
  const locales = config.locale?.list.map((i) => i.code) ?? []
  const variants = config.variant?.list.map((i) => i.code) ?? []

  let combinations: [string | undefined, string | undefined][]

  if (!locales.length && !variants.length) {
    combinations = []
  } else if (!locales.length) {
    combinations = variants.map((v) => [undefined, v])
  } else if (!variants.length) {
    combinations = locales.map((l) => [l, undefined])
  } else {
    combinations = locales.flatMap((l) => variants.map((v) => [l, v] as [string, string]))
  }

  function expand(route: string, locale?: string, variant?: string): string {
    let result = route

    if (locale) {
      result = result.replace('[locale]', locale)
    }

    if (variant) {
      result = result.replace('[variant]', variant)
    }

    return result
  }

  const result = new Set<string>()

  for (const unexpanded of await getRoutes()) {
    for (const [locale, variant] of combinations) {
      let expanded = expand(unexpanded, locale, variant)
      result.add(expanded.endsWith('/index') ? expanded.slice(0, -6) : expanded)
    }
  }

  return result
}
