import { DEFAULT_PUBLIC_LOCALE, normalizePublicLocale } from '~/utils/public-locales'
import { normalizePublicInternalPath } from '~/utils/public-routes'

function normalizePathSuffix(path = '') {
  const match = String(path || '').match(/^[^?#]*(.*)$/)
  return match?.[1] || ''
}

function normalizePathsByLocale(entity, overridePaths = {}) {
  const pathsByLocale = {}

  const addPath = (entryLocale, entryPath) => {
    const normalizedLocale = normalizePublicLocale(entryLocale)
    const normalizedPath = String(entryPath || '').trim()

    if (!normalizedPath) {
      return
    }

    pathsByLocale[normalizedLocale] = normalizePublicInternalPath(normalizedPath, normalizedLocale)
  }

  if (entity?.path) {
    addPath(entity?.locale || DEFAULT_PUBLIC_LOCALE, entity.path)
  }

  for (const localized of Array.isArray(entity?.localized) ? entity.localized : []) {
    addPath(localized?.locale, localized?.path)
  }

  for (const [entryLocale, entryPath] of Object.entries(overridePaths || {})) {
    addPath(entryLocale, entryPath)
  }

  return pathsByLocale
}

function normalizeSectionPathsByLocale(paths = {}) {
  const pathsByLocale = {}

  for (const [entryLocale, entryPath] of Object.entries(paths || {})) {
    const normalizedLocale = normalizePublicLocale(entryLocale)
    const normalizedPath = String(entryPath || '').trim()

    if (!normalizedPath) {
      continue
    }

    pathsByLocale[normalizedLocale] = normalizePublicInternalPath(normalizedPath, normalizedLocale)
  }

  return pathsByLocale
}

function normalizeLocaleList(locales = [], fallbackLocale = DEFAULT_PUBLIC_LOCALE) {
  const values = Array.isArray(locales) ? locales : [locales]
  const normalized = [...new Set(values.map((entry) => normalizePublicLocale(entry)).filter(Boolean))]

  return normalized.length ? normalized : [normalizePublicLocale(fallbackLocale)]
}

export function buildPublicLocaleSwitchContext(entity, options = {}) {
  if (!entity || typeof entity !== 'object') {
    return null
  }

  const kind = String(options.kind || 'detail').trim() || 'detail'
  const fallbackLocale = entity?.locale || DEFAULT_PUBLIC_LOCALE
  const pathsByLocale = normalizePathsByLocale(entity, options.pathsByLocale)
  const sectionPathsByLocale = normalizeSectionPathsByLocale(options.sectionPathsByLocale)
  const detailLocales = normalizeLocaleList(
    options.detailLocales || entity?.availableLocales || Object.keys(pathsByLocale),
    fallbackLocale,
  )
  const sectionPath = String(options.sectionPath || '').trim()

  return {
    kind,
    sectionPath: sectionPath ? normalizePublicInternalPath(sectionPath, DEFAULT_PUBLIC_LOCALE) : '/',
    sectionPathsByLocale,
    detailLocales,
    pathsByLocale,
  }
}

export function usePublicLocaleSwitchContextState() {
  return useState('public-locale-switch-context', () => null)
}

export function useRegisterPublicLocaleSwitchContext(contextRef) {
  const state = usePublicLocaleSwitchContextState()

  watchEffect(() => {
    state.value = unref(contextRef) || null
  })

  onScopeDispose(() => {
    state.value = null
  })

  return state
}

export function resolvePublicLocaleSwitchPath(context, currentPath, targetLocale) {
  const normalizedLocale = normalizePublicLocale(targetLocale)

  if (!context || typeof context !== 'object') {
    return normalizePublicInternalPath(currentPath, normalizedLocale)
  }

  const suffix = normalizePathSuffix(currentPath)
  const explicitTargetPath = context.pathsByLocale?.[normalizedLocale]
  const sectionTargetPath = context.sectionPathsByLocale?.[normalizedLocale]
    || normalizePublicInternalPath(context.sectionPath || '/', normalizedLocale)

  if (context.kind === 'detail') {
    if (explicitTargetPath && context.detailLocales?.includes(normalizedLocale)) {
      return `${explicitTargetPath}${suffix}`
    }

    return `${sectionTargetPath}${suffix}`
  }

  if (explicitTargetPath) {
    return `${explicitTargetPath}${suffix}`
  }

  return normalizePublicInternalPath(currentPath, normalizedLocale)
}
