import { DQRule } from '../models/dq-rules.model'
import { applyFormulaRules } from './applyFormulaRules'

const rule = (overrides: Partial<DQRule>): DQRule => ({
  BASE_COL: 'REVENUE',
  RULE_TYPE: 'HARDFORMULA',
  RULE_VALUE: 'PRICE * VOLUME',
  X: 0,
  ...overrides
})

const columnNames = ['ITEM', 'PRICE', 'VOLUME', 'REVENUE']
const headerPks = ['ITEM']

describe('applyFormulaRules', () => {
  it('leaves the dataset untouched when there are no formula rules', () => {
    const dataSource = [{ ITEM: 'PAPER', PRICE: 4.2, VOLUME: 100, REVENUE: '' }]

    const result = applyFormulaRules(
      dataSource,
      [],
      columnNames,
      dataSource,
      headerPks,
      'sasdemo'
    )

    expect(result).toEqual(dataSource)
  })

  it("injects the row-relative formula string for a HARDFORMULA column (issue's own PRICE*VOLUME example)", () => {
    const dataSource = [
      { ITEM: 'PAPER', PRICE: 4.2, VOLUME: 100, REVENUE: '' },
      { ITEM: 'PEN', PRICE: 61.02, VOLUME: 1971, REVENUE: '' }
    ]

    const result = applyFormulaRules(
      dataSource,
      [rule({})],
      columnNames,
      dataSource,
      headerPks,
      'sasdemo'
    )

    expect(result[0].REVENUE).toEqual('=B1 * C1')
    expect(result[1].REVENUE).toEqual('=B2 * C2')
  })

  it('injects the formula for a SOFTFORMULA column too (only readOnly-ness differs, handled elsewhere)', () => {
    const dataSource = [{ ITEM: 'PAPER', PRICE: 4.2, VOLUME: 100, REVENUE: '' }]

    const result = applyFormulaRules(
      dataSource,
      [rule({ RULE_TYPE: 'SOFTFORMULA' })],
      columnNames,
      dataSource,
      headerPks,
      'sasdemo'
    )

    expect(result[0].REVENUE).toEqual('=B1 * C1')
  })

  it('resolves DC.ORIG_VALUE via the original (pre-edit) row, PK-matched', () => {
    const dataSourceUnchanged = [
      { ITEM: 'PAPER', PRICE: 4.2, VOLUME: 100, NOTE: 'original note' }
    ]
    const dataSource = [{ ITEM: 'PAPER', PRICE: 4.2, VOLUME: 999, NOTE: '' }]

    const result = applyFormulaRules(
      dataSource,
      [rule({ BASE_COL: 'NOTE', RULE_VALUE: 'DC.ORIG_VALUE' })],
      ['ITEM', 'PRICE', 'VOLUME', 'NOTE'],
      dataSourceUnchanged,
      headerPks,
      'sasdemo'
    )

    expect(result[0].NOTE).toEqual('="original note"')
  })

  it('resolves DC.ORIG_VALUE to an empty literal for a newly-added row with no PK match', () => {
    const dataSource = [{ ITEM: 'NEWITEM', PRICE: 1, VOLUME: 1, NOTE: '' }]

    const result = applyFormulaRules(
      dataSource,
      [rule({ BASE_COL: 'NOTE', RULE_VALUE: 'DC.ORIG_VALUE' })],
      ['ITEM', 'PRICE', 'VOLUME', 'NOTE'],
      [],
      headerPks,
      'sasdemo'
    )

    expect(result[0].NOTE).toEqual('=""')
  })

  it('resolves DC.USER_NAME to the current username for every row', () => {
    const dataSource = [
      { ITEM: 'PAPER', PRICE: 4.2, VOLUME: 100, NOTE: '' },
      { ITEM: 'PEN', PRICE: 61.02, VOLUME: 1971, NOTE: '' }
    ]

    const result = applyFormulaRules(
      dataSource,
      [rule({ BASE_COL: 'NOTE', RULE_VALUE: 'DC.USER_NAME' })],
      ['ITEM', 'PRICE', 'VOLUME', 'NOTE'],
      dataSource,
      headerPks,
      'sasdemo'
    )

    expect(result[0].NOTE).toEqual('="sasdemo"')
    expect(result[1].NOTE).toEqual('="sasdemo"')
  })
})
