import Handsontable from 'handsontable'
import { isRegexRuleExempt } from '../../shared/dc-validator/utils/isRegexRuleExempt'
import { parseRegexRule } from '../../shared/dc-validator/utils/parseRegexRule'

const compileRegex = (
  pattern: string | undefined,
  ruleType: 'SOFTREGEX' | 'HARDREGEX'
): RegExp | null => {
  try {
    return pattern ? parseRegexRule(pattern) : null
  } catch (e) {
    console.warn(`${ruleType} - invalid pattern, warning disabled: ${pattern}`)
    return null
  }
}

/**
 * Builds a display-only HOT renderer for HARDREGEX/SOFTREGEX: neither ever
 * returns false from the cell validator here (that's dqValidate's job for
 * HARDREGEX, which blocks submission and paints HOT's own red htInvalid
 * independently of this renderer) - this renderer only adds the matching
 * `REGEX: <pattern>` title, plus a yellow `dc-warning-cell` class when only
 * SOFTREGEX fails, same split as makeNumberFormatRenderer.
 *
 * A column can carry both rules at once. Hard is validated first: a value
 * failing HARDREGEX gets its title (no yellow class - red htInvalid already
 * covers the color), and SOFTREGEX is only evaluated once HARDREGEX passes.
 * This mirrors DcValidator.failsSoftRegex's own precedence.
 *
 * Suppressed on rows marked for delete (_____DELETE__THIS__RECORD_____ =
 * 'Yes') — a warning about data about to be removed is just noise.
 *
 * Falls back to no warning ever showing when a pattern itself is malformed,
 * rather than breaking the cell.
 */
export const makeRegexWarningRenderer = (
  softPattern?: string,
  hardPattern?: string
) => {
  const softRegex = compileRegex(softPattern, 'SOFTREGEX')
  const hardRegex = compileRegex(hardPattern, 'HARDREGEX')

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

  return (
    instance: any,
    td: any,
    row: number,
    col: number,
    prop: string | number,
    value: any,
    cellProperties: any
  ) => {
    baseRenderer(instance, td, row, col, prop, value, cellProperties)

    const markedForDelete =
      instance.getDataAtRowProp(row, '_____DELETE__THIS__RECORD_____') === 'Yes'
    const exempt = isRegexRuleExempt(value)

    const failsHard =
      !!hardRegex && !exempt && !hardRegex.test(value.toString())
    const failsSoft =
      !!softRegex && !exempt && !softRegex.test(value.toString())

    if (markedForDelete) return td

    if (failsHard) {
      td.title = `REGEX: ${hardPattern}`
    } else if (failsSoft) {
      td.classList.add('dc-warning-cell')
      td.title = `REGEX: ${softPattern}`
    }

    return td
  }
}
