import { NormalizedFormat } from './types'

export function applyNormalizedFormat(value: number, format: NormalizedFormat) {
  if (value === 0 && format.zeroPlaceholder) {
    return format.zeroPlaceholder
  }

  const abs = Math.abs(value)
  const decimals = format.decimals ?? 0
  const useGrouping = format.useGrouping ?? true

  const options: Intl.NumberFormatOptions = {
    useGrouping,
    minimumFractionDigits: decimals,
    maximumFractionDigits: decimals,
  }

  if (format.kind === 'percent') {
    options.style = 'percent'
  } else if (format.kind === 'currency' && format.currency) {
    options.style = 'currency'
    options.currency = format.currency
  }

  const intl = new Intl.NumberFormat(navigator.language, options)

  if (value < 0) {
    return format.negativeStyle === 'parentheses' ? `(${intl.format(abs)})` : `-${intl.format(abs)}`
  }
  return intl.format(value)
}

export function applyExcelFormat(value: number, format: string) {
  return applyNormalizedFormat(value, parseExcelFormat(value, format))
}

// Very small subset parser for Excel-ish formats:
// - sections: positive;negative;zero;text
// - % detection
// - decimal place count from '0'/'#'
// - grouping via commas
// - negative parentheses if present in the negative section
// - zero placeholder if third section is a quoted string
function parseExcelFormat(value: number, format: string) {
  const [pos = '', neg = '', zero = ''] = format.split(';')
  const pattern = value < 0 && neg ? neg : value === 0 && zero ? zero : pos // NOSONAR
  const isPercent = pattern.includes('%')

  const dot = pattern.indexOf('.')
  let decimals = 0
  if (dot >= 0) {
    const tail = pattern.slice(dot + 1)
    const match = /^[0#]+/.exec(tail)
    decimals = match ? match[0].length : 0
  }

  const useGrouping = /[#0],[#0]/.test(pattern) || pattern.includes(',,')
  const negativeStyle = neg.includes('(') && neg.includes(')') ? 'parentheses' : 'minus'
  const zeroPlaceholder = zero ? stripQuotes(zero) : undefined

  return {
    kind: isPercent ? 'percent' : 'decimal',
    decimals,
    useGrouping,
    negativeStyle,
    zeroPlaceholder,
  } satisfies NormalizedFormat
}

function stripQuotes(value: string) {
  const matches = /"([^"]*)"/.exec(value)
  const stripped = matches?.[1] ?? value

  return stripped
}

export function ptToRem(pt: number) {
  return pt / 12
}
