import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import ZH_CN from 'dayjs/locale/zh-cn'

import { isToday } from './index'

dayjs.extend(relativeTime)
dayjs.locale(ZH_CN)

export function avatarText(value: string) {
  if (!value) return ''
  const nameArray = value.split(' ')

  return nameArray.map(word => word.charAt(0).toUpperCase()).join('')
}

// TODO: Try to implement this: https://twitter.com/fireship_dev/status/1565424801216311297
export function kFormatter(num: number) {
  const regex = /\B(?=(\d{3})+(?!\d))/g

  return Math.abs(num) > 9999
    ? `${Math.sign(num) * +(Math.abs(num) / 1000).toFixed(1)}k`
    : Math.abs(num).toFixed(0).replace(regex, ',')
}

// 格式化下载量显示，超过1000显示为x.xk格式
export function formatDownloadCount(num: number): string {
  if (!num || num < 1000) return num?.toLocaleString() || '0'

  return `${(num / 1000).toFixed(1)}k`
}

/**
 * Format and return date in Humanize format
 * Intl docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format
 * Intl Constructor: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
 * @param {string} value date to format
 * @param {Intl.DateTimeFormatOptions} formatting Intl object to format with
 */
export function formatDate(
  value: string,
  formatting: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' },
) {
  if (!value) return value

  return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
}

/**
 * Return short human friendly month representation of date
 * Can also convert date to only time if date is of today (Better UX)
 * @param {string} value date to format
 * @param {boolean} toTimeForCurrentDay Shall convert to time if day is today/current
 */
export function formatDateToMonthShort(value: string, toTimeForCurrentDay = true) {
  const date = new Date(value)
  let formatting: Record<string, string> = { month: 'short', day: 'numeric' }

  if (toTimeForCurrentDay && isToday(date)) formatting = { hour: 'numeric', minute: 'numeric' }

  return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
}

export const prefixWithPlus = (value: number) => (value > 0 ? `+${value}` : value)

// 格式化为Sxx
export const formatSeason = (value: string) => (value ? `S${value.padStart(2, '0')}` : '')

// 格式化为xx[TGMK]B
export function formatFileSize(bytes: number, decimals = 2, prefix = false) {
  // 负数标记
  let negative = false
  let size = bytes
  if (bytes < 0) {
    negative = true
    size = Math.abs(bytes)
  }

  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let unitIndex = 0

  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }
  if (negative) return `-${size.toFixed(decimals)} ${units[unitIndex]}`
  else
    return prefix ? `+${size.toFixed(decimals)} ${units[unitIndex]}` : `${size.toFixed(decimals)} ${units[unitIndex]}`
}

// 将时间秒格式化为时分秒
export function formatSeconds(seconds: number) {
  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  const remainingSeconds = seconds % 60

  let formattedTime = ''

  if (hours > 0) formattedTime += `${hours}小时`

  if (minutes > 0) formattedTime += `${minutes}分`

  if ((remainingSeconds > 0 || formattedTime === '') && hours <= 0) formattedTime += `${remainingSeconds}秒`

  return formattedTime
}

// YYYY-MM-DD 转化为Date
export function parseDate(dateString: string): Date | null {
  if (!dateString) return null
  const [year, month, day] = dateString.split('-').map(Number)

  return new Date(year, month - 1, day)
}

// 文件大小格式化
export function formatBytes(bytes: number, decimals = 2) {
  if (bytes === 0) return '0 bytes'

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`
}

// 格式化剧集列表
export function formatEp(nums: number[]): string {
  if (!nums.length) return ''

  if (nums.length === 1) return nums[0].toString()

  // 将数组升序排序
  nums.sort((a, b) => a - b)
  const formattedRanges: string[] = []
  let start = nums[0]
  let end = nums[0]

  for (let i = 1; i < nums.length; i++) {
    if (nums[i] === end + 1) {
      end = nums[i]
    } else {
      if (start === end) formattedRanges.push(start.toString())
      else formattedRanges.push(`${start.toString()}-${end.toString()}`)

      start = end = nums[i]
    }
  }

  if (start === end) formattedRanges.push(start.toString())
  else formattedRanges.push(`${start.toString()}-${end.toString()}`)

  return formattedRanges.join('、')
}

// 将yyyy-mm-dd hh:mm:ss转换为时间差，如：1小时前，1天前
export function formatDateDifference(dateString: string): string {
  if (!dateString) return ''
  return dayjs(dateString).fromNow()
}

// 格式化评份，如为10及以下的数按原值显示，否则格式化为xxM、xxK显示
export function formatRating(rating: number): string {
  if (!rating) return ''
  if (rating <= 10) return rating.toString()
  if (rating < 1000) return rating.toLocaleString()
  if (rating < 1000 * 1000) return `${(rating / 1000).toFixed(1)}K`
  return `${(rating / 1000 / 1000).toFixed(1)}M`
}
