import { VaMessagingService, VaMessage } from './va-messaging.service'

// Sample message taken from the official SAS DDC docs (brush column included).
const SAMPLE = {
  version: '1',
  resultName: 'dd40',
  rowCount: 3,
  availableRowCount: 3,
  data: [
    ['Finch', 95000.0, 0.4285],
    ['Jones', 26000.0, 0.0],
    ['Smith', 108000.0, 0.5]
  ],
  columns: [
    { name: 'bi184', label: 'dealer', type: 'string' },
    {
      name: 'bi258',
      label: 'sales',
      type: 'number',
      usage: 'quantitative',
      aggregation: 'sum'
    },
    { name: 'ri1', type: 'number', usage: 'brush' }
  ]
}

describe('VaMessagingService', () => {
  let service: VaMessagingService

  beforeEach(() => {
    service = new VaMessagingService()
  })

  describe('parseMessage', () => {
    it('parses a valid DDC message and defaults parameters to []', () => {
      const msg = service.parseMessage({ data: SAMPLE } as MessageEvent)
      expect(msg).not.toBeNull()
      expect(msg!.resultName).toBe('dd40')
      expect(msg!.rowCount).toBe(3)
      expect(msg!.parameters).toEqual([])
    })

    it('returns null for unrelated / malformed messages', () => {
      expect(service.parseMessage({ data: null } as MessageEvent)).toBeNull()
      expect(
        service.parseMessage({ data: 'hello' } as unknown as MessageEvent)
      ).toBeNull()
      expect(
        service.parseMessage({ data: { columns: [] } } as MessageEvent)
      ).toBeNull()
    })
  })

  describe('dataColumns', () => {
    it('excludes brush columns and keeps original indices', () => {
      const msg = service.parseMessage({ data: SAMPLE } as MessageEvent)!
      const cols = service.dataColumns(msg)
      expect(cols.map((c) => c.column.name)).toEqual(['bi184', 'bi258'])
      expect(cols.map((c) => c.index)).toEqual([0, 1])
    })
  })

  describe('onData', () => {
    const sameOrigin = window.location.origin

    it('invokes the callback for valid messages and unsubscribes cleanly', () => {
      const received: VaMessage[] = []
      const off = service.onData((m) => received.push(m))

      window.dispatchEvent(
        new MessageEvent('message', { data: SAMPLE, origin: sameOrigin })
      )
      expect(received.length).toBe(1)
      expect(received[0].resultName).toBe('dd40')

      // unrelated traffic is ignored
      window.dispatchEvent(
        new MessageEvent('message', { data: { foo: 1 }, origin: sameOrigin })
      )
      expect(received.length).toBe(1)

      off()
      window.dispatchEvent(
        new MessageEvent('message', { data: SAMPLE, origin: sameOrigin })
      )
      expect(received.length).toBe(1)
    })

    it('rejects messages from an untrusted origin', () => {
      const received: VaMessage[] = []
      service.onData((m) => received.push(m))

      window.dispatchEvent(
        new MessageEvent('message', {
          data: SAMPLE,
          origin: 'https://evil.example.com'
        })
      )
      expect(received.length).toBe(0)
    })
  })
})
