import { resolvePublicUiValue } from '~/i18n/public-ui'
import { DEFAULT_PUBLIC_LOCALE, normalizePublicLocale } from '~/utils/public-locales'

export function sortByOrder(items = [], key = 'sortOrder') {
  return [...items].sort((left, right) => Number(left?.[key] || 0) - Number(right?.[key] || 0))
}

export function toPublicIntlLocale(locale = 'en') {
  const normalized = normalizePublicLocale(locale)

  return {
    en: 'en-US',
    fr: 'fr-FR',
    es: 'es-ES',
    ru: 'ru-RU',
    de: 'de-DE',
    ka: 'ka-GE',
    it: 'it-IT',
    ar: 'ar',
    he: 'he-IL',
    pl: 'pl-PL',
    tr: 'tr-TR',
  }[normalized] || 'en-US'
}

export function formatPublicMoney(amount, currencyCode = 'USD', locale = 'en', options = {}) {
  const numericAmount = Number(amount || 0)

  if (!Number.isFinite(numericAmount)) {
    return ''
  }

  const hasFraction = options.forceFraction === true
    || (options.forceFraction !== false && Math.round(numericAmount) !== numericAmount)

  return new Intl.NumberFormat(toPublicIntlLocale(locale), {
    style: 'currency',
    currency: currencyCode || 'USD',
    minimumFractionDigits: hasFraction ? 2 : 0,
    maximumFractionDigits: hasFraction ? 2 : 0,
  }).format(numericAmount)
}

export function formatPublicDateTime(value, locale = 'en', options = {}) {
  if (!value) {
    return ''
  }

  const date = new Date(value)

  if (Number.isNaN(date.getTime())) {
    return ''
  }

  return new Intl.DateTimeFormat(toPublicIntlLocale(locale), {
    month: options.month || 'short',
    day: options.day || 'numeric',
    year: options.year,
    hour: options.hour || 'numeric',
    minute: options.minute || '2-digit',
  }).format(date)
}

export function formatPublicDateRange(start, end, locale = 'en', options = {}) {
  if (!start || !end) {
    return ''
  }

  const startDate = new Date(start)
  const endDate = new Date(end)

  if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
    return ''
  }

  const formatter = new Intl.DateTimeFormat(toPublicIntlLocale(locale), {
    month: options.month || 'short',
    day: options.day || 'numeric',
  })

  return `${formatter.format(startDate)} - ${formatter.format(endDate)}`
}

export function formatContentDate(value, locale = 'en-US') {
  if (!value) {
    return ''
  }

  const date = new Date(value)

  if (Number.isNaN(date.getTime())) {
    return ''
  }

  return new Intl.DateTimeFormat(locale, {
    month: 'long',
    day: 'numeric',
    year: 'numeric',
  }).format(date)
}

export function replaceDateToken(template, dateLabel) {
  return String(template || '').replace(':date', dateLabel || '')
}

export function splitHeadline(value) {
  const words = String(value || '').trim().split(/\s+/).filter(Boolean)

  if (words.length <= 1) {
    return {
      leading: words[0] || '',
      accent: '',
    }
  }

  return {
    leading: words.slice(0, -1).join(' '),
    accent: words.at(-1) || '',
  }
}

export function buildResolvedPageSeo(page, origin = '', options = {}) {
  const seo = page?.seo || {}
  const localized = Array.isArray(page?.localized) ? page.localized : []
  const canonicalPath = page?.path
    || localized.find((entry) => normalizePublicLocale(entry?.locale) === DEFAULT_PUBLIC_LOCALE)?.path
    || localized[0]?.path
    || ''
  const fallbackCanonical = canonicalPath ? `${origin}${canonicalPath}` : ''
  const hreflang = Array.isArray(seo?.hreflang) && seo.hreflang.length
    ? seo.hreflang
    : localized
      .filter((entry) => entry?.locale && (entry?.href || entry?.path))
      .map((entry) => ({
        locale: entry.locale,
        href: entry.href || `${origin}${entry.path}`,
      }))

  return {
    title: seo.title || page?.title || options.title || '',
    description: seo.description || page?.excerpt || options.description || '',
    ogTitle: seo.ogTitle || seo.title || page?.title || options.title || '',
    ogDescription: seo.ogDescription || seo.description || page?.excerpt || options.description || '',
    ogImage: seo.ogImage || options.ogImage || '',
    canonical: seo.canonical || fallbackCanonical,
    robots: seo.robots || 'index,follow',
    hreflang,
    xDefault: seo.xDefault
      || localized.find((entry) => normalizePublicLocale(entry?.locale) === DEFAULT_PUBLIC_LOCALE)?.href
      || fallbackCanonical,
  }
}

export function resolvePublicDayUnit(count, locale = 'en') {
  const normalizedLocale = normalizePublicLocale(locale)
  const numericCount = Math.abs(Number(count || 0))

  if (normalizedLocale === 'ru') {
    const mod10 = numericCount % 10
    const mod100 = numericCount % 100

    if (mod10 === 1 && mod100 !== 11) {
      return resolvePublicUiValue(locale, 'common.day', 'день')
    }

    if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
      return resolvePublicUiValue(locale, 'common.days', 'дня')
    }

    return resolvePublicUiValue(locale, 'common.daysMany', 'дней')
  }

  if (normalizedLocale === 'ka') {
    return resolvePublicUiValue(locale, 'common.days', 'დღე')
  }

  return numericCount === 1
    ? resolvePublicUiValue(locale, 'common.day', 'day')
    : resolvePublicUiValue(locale, 'common.days', 'days')
}

export function formatPublicDayCount(count, locale = 'en', templatePath = 'common.dayCountTemplate') {
  const template = resolvePublicUiValue(locale, templatePath, '{count} {unit}')

  return String(template)
    .replace('{count}', String(Number(count || 0)))
    .replace('{unit}', resolvePublicDayUnit(count, locale))
}

export function localizePublicVehicleCategory(value, locale = 'en') {
  const normalizedValue = String(value || '').trim().toLowerCase()
  const path = {
    economy: 'vehicles.categories.economy',
    sedan: 'vehicles.categories.sedan',
    suv: 'vehicles.categories.suv',
    van: 'vehicles.categories.vans',
    vans: 'vehicles.categories.vans',
    premium: 'vehicles.categories.premium',
    luxury: 'vehicles.categories.premium',
  }[normalizedValue]

  if (!path) {
    return String(value || '').trim()
  }

  return resolvePublicUiValue(locale, path, String(value || '').trim())
}

export function localizePublicTransmission(value, locale = 'en') {
  const normalizedValue = String(value || '').trim().toLowerCase()
  const path = {
    automatic: 'vehicles.transmissionAutomatic',
    auto: 'vehicles.transmissionAutomatic',
    manual: 'vehicles.transmissionManual',
  }[normalizedValue]

  if (!path) {
    return String(value || '').trim()
  }

  return resolvePublicUiValue(locale, path, String(value || '').trim())
}

export function localizePublicFuel(value, locale = 'en') {
  const normalizedValue = String(value || '').trim().toLowerCase()
  const path = {
    petrol: 'vehicles.fuelPetrol',
    gasoline: 'vehicles.fuelPetrol',
    diesel: 'vehicles.fuelDiesel',
    hybrid: 'vehicles.fuelHybrid',
    electric: 'vehicles.fuelElectric',
    ev: 'vehicles.fuelElectric',
  }[normalizedValue]

  if (!path) {
    return String(value || '').trim()
  }

  return resolvePublicUiValue(locale, path, String(value || '').trim())
}

export function formatPublicSeatCount(count, locale = 'en') {
  const numericCount = Number(count || 0)

  if (!Number.isFinite(numericCount) || numericCount <= 0) {
    return ''
  }

  return resolvePublicUiValue(locale, 'vehicles.seatCountTemplate', '{count} {label}')
    .replace('{count}', String(numericCount))
    .replace('{label}', resolvePublicUiValue(locale, 'vehicles.seats', 'Seats'))
}

export function formatPublicQuoteLineLabel(line, options = {}) {
  const locale = options.locale || 'en'
  const currencyCode = options.currencyCode || 'USD'
  const days = Number(options.days || 0)
  const amount = Number(line?.rateAmount ?? line?.unitAmount ?? (line?.amount || 0))
  const rawLabel = String(line?.label || '').trim()

  if (String(line?.code || '').trim() !== 'rental') {
    return rawLabel
  }

  const template = resolvePublicUiValue(locale, 'checkout.baseRentalLineTemplate', 'Rental ({period} × {rate})')

  return String(template)
    .replace('{period}', formatPublicDayCount(days, locale, 'checkout.rentalPeriodCountTemplate'))
    .replace('{rate}', formatPublicMoney(amount, currencyCode, locale))
}

export function resolvePublicApiError(error, fallback = '', locale = 'en') {
  const message = String(error?.data?.message || error?.message || '').trim()
  const normalizedLocale = normalizePublicLocale(locale)

  if (normalizedLocale === 'en' && message) {
    return message
  }

  return fallback || message
}

function isLocalProxyHostname(hostname = '') {
  return ['127.0.0.1', 'localhost', '::1', '[::1]'].includes(String(hostname || '').toLowerCase())
}

export function resolvePublicAssetUrl(value, apiBaseUrl = '') {
  const assetUrl = String(value || '').trim()

  if (!assetUrl || !/^https?:\/\//i.test(assetUrl)) {
    return assetUrl
  }

  try {
    const proxyUrl = new URL(String(apiBaseUrl || '').trim())

    if (!isLocalProxyHostname(proxyUrl.hostname)) {
      return assetUrl
    }

    const remoteUrl = new URL(assetUrl)

    if (!/^\/(media|storage)\//.test(remoteUrl.pathname)) {
      return assetUrl
    }

    remoteUrl.protocol = proxyUrl.protocol
    remoteUrl.host = proxyUrl.host

    return remoteUrl.toString()
  } catch {
    return assetUrl
  }
}
