let idSeed = 0

function clampInteger(value, minValue, maxValue, fallback) {
  const numberValue = Number(value)
  if (!Number.isFinite(numberValue)) return fallback

  return Math.min(Math.max(Math.round(numberValue), minValue), maxValue)
}

function createId(prefix = 'id') {
  idSeed += 1

  return `${prefix}-${Date.now()}-${idSeed}`
}

function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

function getWxApi() {
  return typeof wx === 'undefined' ? {} : wx
}

function isCancelError(error) {
  const message = String(error && (error.errMsg || error.message || error) || '')

  return /cancel|取消/i.test(message)
}

function toFiniteNumber(value, fallback = 0) {
  if (typeof value === 'string') {
    const text = value.trim()
    const directValue = Number(text)
    if (Number.isFinite(directValue)) return directValue

    const match = text.match(/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/i)
    const textValue = match ? Number(match[0]) : NaN

    return Number.isFinite(textValue) ? textValue : fallback
  }

  const numberValue = Number(value)

  return Number.isFinite(numberValue) ? numberValue : fallback
}

function formatFixedValue(value, precision = 2) {
  const numberValue = toFiniteNumber(value, NaN)
  if (!Number.isFinite(numberValue)) return '--'

  const text = numberValue.toFixed(precision)
  return Number(text) === 0 ? (0).toFixed(precision) : text
}

function parseHexInteger(value, fallback = 0) {
  const text = String(value === undefined || value === null ? '' : value).trim()
  if (!text) return fallback

  const parsed = parseInt(text, 16)
  return Number.isFinite(parsed) ? parsed : fallback
}

function normalizeTextValue(value) {
  return String(value === undefined || value === null ? '' : value)
}

function pickFields(source, fields = []) {
  return fields.reduce((result, field) => {
    if (source && source[field] !== undefined && source[field] !== null && source[field] !== '') {
      result[field] = source[field]
    }

    return result
  }, {})
}

function padHex(value, length = 4) {
  return Number(value || 0).toString(16).toUpperCase().padStart(length, '0')
}

module.exports = {
  clampInteger,
  createId,
  delay,
  formatFixedValue,
  getWxApi,
  isCancelError,
  normalizeTextValue,
  padHex,
  pickFields,
  parseHexInteger,
  toFiniteNumber
}
