import Types from '@/common/utils/types'
import { isNumStr } from '@/common/utils/objects.ts'
import {
  type DateObjectUnits,
  DateTime,
} from 'luxon'

/*
 * 文档：https://luxon.nodejs.cn/
 */
export class FMT {
  static readonly month: string = 'yyyy-MM'
  static readonly date: string = 'yyyy-MM-dd'
  static readonly time: string = 'HH:mm'
  static readonly time_sec: string = 'HH:mm:ss'
  static readonly date_time: string = 'yyyy-MM-dd HH:mm'
  static readonly date_time_sec: string = 'yyyy-MM-dd HH:mm:ss'
  static readonly date_zh: string = 'yyyy年MM月dd日'
  static readonly time_zh: string = 'HH时mm分'
  static readonly time_sec_zh: string = 'HH时mm分ss秒'
  static readonly date_time_zh: string = 'yyyy年MM月dd日HH时mm分'
  static readonly date_time_sec_zh: string = 'yyyy年MM月dd日HH时mm分ss秒'
  static readonly timestamp: string = 'x'
}

/**
 * 获取当前时间
 *
 * @return luxon 库的时间对象
 */
function now() {
  return DateTime.now()
}

/**
 * 解析时间
 *
 * @param date JS 时间对象、时间戳（数字、字符串）、时间字符串、时间描述对象
 * @param fmt 时间格式（仅时间字符串需要此参数，默认：yyyy-MM-dd HH:mm:ss）
 * @return luxon 库的时间对象
 */
function parse(date: Date | number | string | DateObjectUnits, fmt: string = FMT.date_time_sec) {
  if (Types.isDate(date)) {
    return DateTime.fromJSDate(date as Date)
  } else if (Types.isNumber(date) || isNumStr(date)) {
    return DateTime.fromMillis(Number(date))
  } else if (Types.isString(date)) {
    return DateTime.fromFormat(date as string, fmt)
  } else {
    return DateTime.fromObject(date as DateObjectUnits)
  }
}

/**
 * 格式化时间
 *
 * @param date luxon 库的时间对象、JS 时间对象
 * @param fmt 时间格式（仅时间字符串需要此参数，默认：yyyy-MM-dd HH:mm:ss）
 */
function format(date?: DateTime<true | false> | Date, fmt: string = FMT.date_time_sec) {
  if (date == null) return ''
  if (Types.isDate(date)) {
    return DateTime.fromJSDate(date as Date).toFormat(fmt)
  } else {
    return (date as DateTime<true | false>).toFormat(fmt)
  }
}

/**
 * 时间美化（如：1年前）
 *
 * @param date luxon 库的时间对象、JS 时间对象、时间戳（数字、字符串）、时间字符串、时间描述对象
 * @param other 另一个时间
 */
function pretty(date: DateTime<true | false> | Date | number | string, other: DateTime<true | false> | Date | number | string = DateTime.now()) {
  if (!(date instanceof DateTime)) {
    date = parse(date)
  }
  if (!(other instanceof DateTime)) {
    other = parse(other)
  }

  let {
    seconds,
    minutes,
    hours,
    days,
    weeks,
    months,
    years,
  } = date.diff(other, [ 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years' ])

  if (years > 0) {
    return `${years}年后`
  } else if (years < 0) {
    return `${-years}年前`
  }

  if (months > 0) {
    return `${months}个月后`
  } else if (months < 0) {
    return `${-months}个月前`
  }

  if (weeks > 0) {
    return `${weeks}周后`
  } else if (weeks < 0) {
    return `${-weeks}周前`
  }

  if (days > 0) {
    return `${days}天后`
  } else if (days < 0) {
    return `${-days}天前`
  }

  if (hours > 0) {
    return `${hours}小时后`
  } else if (hours < 0) {
    return `${-hours}小时前`
  }

  if (minutes > 0) {
    return `${minutes}分钟后`
  } else if (minutes > -5 && minutes <= -1) {
    return '刚刚'
  } else if (minutes <= -5) {
    return `${-minutes}分钟前`
  }

  if (seconds > 0) {
    return '片刻后'
  } else if (seconds < 0) {
    return '刚刚'
  }

  return '现在'
}

function prettyDuration(date: DateTime<true | false> | Date | number | string, other: DateTime<true | false> | Date | number | string = DateTime.now()) {
  if (!(date instanceof DateTime)) {
    date = parse(date)
  }
  if (!(other instanceof DateTime)) {
    other = parse(other)
  }

  let {
    seconds,
    minutes,
    hours,
    days,
    weeks,
    months,
    years,
  } = date.diff(other, [ 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years' ])

  if (years > 0) {
    return `${years}年`
  } else if (years < 0) {
    return `${-years}年`
  }

  if (months > 0) {
    return `${months}个月`
  } else if (months < 0) {
    return `${-months}个月`
  }

  if (weeks > 0) {
    return `${weeks}周`
  } else if (weeks < 0) {
    return `${-weeks}周`
  }

  if (days > 0) {
    return `${days}天`
  } else if (days < 0) {
    return `${-days}天`
  }

  if (hours > 0) {
    return `${hours}小时`
  } else if (hours < 0) {
    return `${-hours}小时`
  }

  if (minutes > 0) {
    return `${minutes}分钟`
  } else if (minutes < 0) {
    return `${minutes}分钟`
  }

  if (seconds > 0) {
    return `${seconds}秒`
  } else {
    return '小于 1 秒'
  }
}

function beginOfDay(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.startOf('day')
}

function endOfDay(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.endOf('day')
}

function beginOfMonth(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.startOf('month')
}

function endOfMonth(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.endOf('month')
}

function beginOfWeek(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.startOf('week')
}

function endOfWeek(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.endOf('week')
}

function beginOfYear(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.startOf('year')
}

function endOfYear(date?: DateTime<true | false>) {
  if (date == null) {
    date = now()
  }
  return date.endOf('year')
}


function toDate(date: DateTime<true | false>) {
  return date.toJSDate()
}

export default {
  now,
  parse,
  format,
  pretty,
  FMT,
  endOfMonth,
  beginOfMonth,
  beginOfDay,
  endOfDay,
  beginOfWeek,
  endOfWeek,
  beginOfYear,
  endOfYear,
  toDate,
  prettyDuration,
}
