import { type JsonValue } from '../utils/content-canonical'
import { buildContent, expandContent } from '../utils/content-reduced'
import { useContentPreference } from './useContentPreference'
import config from 'virtual:content/content.config'
import shortcuts from 'virtual:content/shortcuts'

export function useContentInjected(slug?: string, global?: JsonValue, local?: JsonValue) {
  if (!slug) {
    throw new Error(
      'useContentInjected called without arguments, there might be a problem with the Vite plugin'
    )
  }

  const route = useRoute()
  const { preferredLocale, preferredVariant } = useContentPreference()

  const lo = computed(() => (route.params.locale as string | undefined) ?? preferredLocale.value)
  const va = computed(() => (route.params.variant as string | undefined) ?? preferredVariant.value)

  const g = computed(() => getContent('content.global', lo.value, va.value, global, local))
  const l = computed(() => getContent(slug, lo.value, va.value, global, local))

  function path(page?: string, options?: { locale?: string; variant?: string }) {
    return computed(() => {
      let result: string // don't touch page, this will mess with reactivity

      if (page === undefined) {
        result = route.fullPath

        function replace(what: string, value: string) {
          // replaces only the first occurrence
          const expression = new RegExp(`/${what}(?=[/?#]|$)`)
          return result.replace(expression, `/${value}`)
        }

        result = lo.value ? replace(lo.value, '[locale]') : result
        result = va.value ? replace(va.value, '[variant]') : result
      } else {
        const index = page.search(/[?#]/)
        const path = index === -1 ? page : page.slice(0, index)

        if (path in shortcuts) {
          result = shortcuts[path] + page.slice(index === -1 ? page.length : index)
        } else {
          result = page
        }
      }

      if (!result.startsWith('/')) {
        result = '/' + result
      }

      result = lo.value ? result.replace('[locale]', options?.locale ?? lo.value ?? '') : result
      result = va.value ? result.replace('[variant]', options?.variant ?? va.value ?? '') : result

      return result
    })
  }

  return {
    locale: lo,
    variant: va,
    global: g as ComputedRef,
    local: l as ComputedRef,
    g: g as ComputedRef,
    l: l as ComputedRef,
    path: path,
    p: path,
  }
}

const cache = new Map<string, JsonValue | undefined>()

function getContent(
  slug: string,
  locale?: string,
  variant?: string,
  global?: JsonValue,
  local?: JsonValue
): JsonValue | undefined {
  const key = `${slug}${locale}${variant}`

  const hit = cache.get(key)
  if (hit !== undefined) {
    return hit
  }

  const locales: string[] = config.locale?.list.map((l) => l.code) ?? []
  const variants: string[] = config.variant?.list.map((v) => v.code) ?? []

  const content = slug === 'content.global' ? global : local

  let [reduced, expand] =
    content === undefined
      ? [undefined, false]
      : buildContent(locale, locales, variant, variants, content)

  if (reduced && expand) {
    if (slug === 'content.global') {
      reduced = expandContent(reduced, [reduced])
    } else {
      const g = getContent('content.global', locale, variant, global, local)
      reduced = expandContent(reduced, g ? [reduced, g] : [reduced])
    }
  }

  cache.set(key, reduced)
  return reduced
}
