const faDigits = '۰۱۲۳۴۵۶۷۸۹'
const arDigits = '٠١٢٣٤٥٦٧٨٩'

const faMonths: Record<string, number> = {
  فروردین: 1,
  اردیبهشت: 2,
  خرداد: 3,
  تیر: 4,
  مرداد: 5,
  شهریور: 6,
  مهر: 7,
  آبان: 8,
  آذر: 9,
  دی: 10,
  بهمن: 11,
  اسفند: 12,
}

type DateLike = {
  date?: string | null
  dateFa?: string | null
  dateEn?: string | null
  dateIso?: string | null
  createdAt?: string | null
  updatedAt?: string | null
}

const normalizeDigits = (value: string) =>
  value.replace(/[۰-۹٠-٩]/g, (d) => {
    const fa = faDigits.indexOf(d)
    if (fa >= 0) return String(fa)
    const ar = arDigits.indexOf(d)
    return ar >= 0 ? String(ar) : d
  })

const currentPersianYear = () => {
  try {
    const parts = new Intl.DateTimeFormat('en-US-u-ca-persian', { year: 'numeric' }).formatToParts(new Date())
    const year = Number(parts.find((part) => part.type === 'year')?.value)
    if (Number.isFinite(year) && year > 1300) return year
  } catch {
    /* keep deterministic fallback for browsers without Persian calendar support */
  }
  return 1405
}

const parsePersianDateKey = (value?: string | null) => {
  if (!value) return 0
  const normalized = normalizeDigits(value)
  const day = Number((normalized.match(/\d{1,2}/) || ['0'])[0])
  const explicitYear = Number((normalized.match(/\d{4}/) || ['0'])[0])
  const year = explicitYear || currentPersianYear()
  const month = Object.entries(faMonths).find(([name]) => value.includes(name))?.[1] ?? 0
  return year && month && day ? year * 10000 + month * 100 + day : 0
}

const parseGregorianDateKey = (value?: string | null) => {
  if (!value) return 0
  const parsed = Date.parse(value)
  if (!Number.isFinite(parsed)) return 0
  const date = new Date(parsed)
  return date.getUTCFullYear() * 10000 + (date.getUTCMonth() + 1) * 100 + date.getUTCDate()
}

export const getDateSortKey = (item: DateLike) => {
  const persianKey = parsePersianDateKey(item.dateFa || item.date)
  if (persianKey) return persianKey
  return (
    parseGregorianDateKey(item.dateIso) ||
    parseGregorianDateKey(item.dateEn) ||
    parseGregorianDateKey(item.updatedAt) ||
    parseGregorianDateKey(item.createdAt)
  )
}

export const sortByDateDesc = <T extends DateLike>(items: T[]) =>
  [...items].sort((a, b) => getDateSortKey(b) - getDateSortKey(a))

const getPublishedSortKey = (item: DateLike) => {
  const published = Date.parse(item.createdAt || '')
  if (Number.isFinite(published)) return published

  const updated = Date.parse(item.updatedAt || '')
  if (Number.isFinite(updated)) return updated

  return getDateSortKey(item)
}

export const sortByPublishedDesc = <T extends DateLike>(items: T[]) =>
  [...items].sort((a, b) => getPublishedSortKey(b) - getPublishedSortKey(a))
