const ISO_DATE_TIME_PATTERN =
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?$/

export function isIsoDateTimeString(value: unknown): value is string {
  return typeof value === 'string' && ISO_DATE_TIME_PATTERN.test(value.trim())
}

export function formatDateTime(value: string | null | undefined, fallback = '-') {
  const normalized = String(value || '').trim()

  if (!normalized) {
    return fallback
  }

  const date = new Date(normalized)

  if (Number.isNaN(date.getTime())) {
    return normalized.replace('T', ' ').replace('Z', '')
  }

  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

export function normalizeDateTimeValue(value: unknown): unknown {
  if (Array.isArray(value)) {
    return value.map((item) => normalizeDateTimeValue(item))
  }

  if (value && typeof value === 'object') {
    return Object.fromEntries(
      Object.entries(value).map(([key, currentValue]) => [
        key,
        normalizeDateTimeValue(currentValue),
      ]),
    )
  }

  if (isIsoDateTimeString(value)) {
    return formatDateTime(value, '')
  }

  return value
}

export function stringifyDisplayJson(value: unknown, space = 2) {
  return JSON.stringify(normalizeDateTimeValue(value), null, space)
}
