import Handsontable from 'handsontable'

/**
 * Builds a display-only HOT renderer that formats numeric cell values using
 * Intl.NumberFormat. The stored/submitted value is never changed — only the
 * rendered text. `ruleValue` is a JSON string of Intl.NumberFormat options
 * (e.g. '{"style":"currency","currency":"EUR","minimumFractionDigits":2}').
 *
 * Falls back to the plain text renderer when the JSON is invalid, the options
 * are rejected by Intl.NumberFormat, or the value is not a finite number.
 */
export const makeNumberFormatRenderer = (ruleValue?: string) => {
  let formatter: Intl.NumberFormat | null = null

  try {
    const options = ruleValue ? JSON.parse(ruleValue) : {}
    formatter = new Intl.NumberFormat(window.navigator.language, options)
  } catch (e) {
    console.warn(
      `NUMBER_FORMAT - invalid Intl.NumberFormat options: ${ruleValue}`
    )
    formatter = null
  }

  const baseRenderer = Handsontable.renderers.getRenderer('text')

  return (
    instance: any,
    td: any,
    row: number,
    col: number,
    prop: string | number,
    value: any,
    cellProperties: any
  ) => {
    // Render via the base text renderer first to preserve cell styling/classes
    // (readOnly, alignment, etc.), then override the displayed text.
    baseRenderer(instance, td, row, col, prop, value, cellProperties)

    const num = Number(value)
    if (
      formatter &&
      value !== null &&
      value !== undefined &&
      value !== '' &&
      !isNaN(num)
    ) {
      td.textContent = formatter.format(num)
    }

    return td
  }
}

/**
 * Custom renderer for HOT cell
 * Used to show error icon
 */
export const errorRenderer = (
  instance: any,
  td: any,
  row: number,
  col: number,
  prop: string,
  value: any,
  cellProperties: any
) => {
  addDarkClass(td)

  td.innerHTML = `${
    value ? value.toString() : ''
  } <cds-icon shape="exclamation-triangle" status="warning"></cds-icon>`

  return td
}

/**
 * Custom renderer for HOT cell
 * Used to revert cell back to original state (no spinner, no error)
 */
export const noSpinnerRenderer = (
  instance: any,
  td: any,
  row: number,
  col: number,
  prop: string,
  value: any,
  cellProperties: any
) => {
  addDarkClass(td)

  td.innerHTML = value ? value : ''

  return td
}

/**
 * Custom renderer for HOT cell
 * Used to show loading spinner in the cell
 * (Spinner shown whilst waiting for SAS to respond)
 */
export const spinnerRenderer = (
  instance: any,
  td: any,
  row: number,
  col: number,
  prop: string,
  value: any,
  cellProperties: any
) => {
  addDarkClass(td)

  td.innerHTML = `${
    value ? value.toString() : ''
  } <span class="spinner spinner-sm vertical-align-middle"></span>`

  return td
}

/**
 * Adds a htDark class to a TD element if not existing
 */
const addDarkClass = (td: any) => {
  if (!td.classList.contains('htDark')) {
    td.classList.add('htDark')
  }
}
