import { describe, it, expect } from 'vitest'
import { buildUpdateQuery, getAllowedColumns } from '../../server/utils/queryBuilder.js'

describe('queryBuilder', () => {
  describe('buildUpdateQuery', () => {
    it('builds valid UPDATE query for devices', () => {
      const { query, params } = buildUpdateQuery('devices', null, {
        name: 'Test Device',
        lat: 40.7128,
      })
      expect(query).toBe('UPDATE devices SET name = ?, lat = ? WHERE id = ?')
      expect(params).toEqual(['Test Device', 40.7128])
    })

    it('builds valid UPDATE query for users', () => {
      const { query, params } = buildUpdateQuery('users', null, {
        role: 'admin',
        identifier: 'testuser',
      })
      expect(query).toBe('UPDATE users SET role = ?, identifier = ? WHERE id = ?')
      expect(params).toEqual(['admin', 'testuser'])
    })

    it('builds valid UPDATE query for pois', () => {
      const { query, params } = buildUpdateQuery('pois', null, {
        label: 'Test POI',
        lat: 40.7128,
        lng: -74.0060,
      })
      expect(query).toBe('UPDATE pois SET label = ?, lat = ?, lng = ? WHERE id = ?')
      expect(params).toEqual(['Test POI', 40.7128, -74.0060])
    })

    it('returns empty query when no updates', () => {
      const { query, params } = buildUpdateQuery('devices', null, {})
      expect(query).toBe('')
      expect(params).toEqual([])
    })

    it('throws error for unknown table', () => {
      expect(() => {
        buildUpdateQuery('unknown_table', null, { name: 'test' })
      }).toThrow('Unknown table: unknown_table')
    })

    it('throws error for invalid column name', () => {
      expect(() => {
        buildUpdateQuery('devices', null, { invalid_column: 'test' })
      }).toThrow('Invalid column: invalid_column for table: devices')
    })

    it('prevents SQL injection attempts in column names', () => {
      expect(() => {
        buildUpdateQuery('devices', null, { 'name\'; DROP TABLE devices; --': 'test' })
      }).toThrow('Invalid column')
    })

    it('allows custom allowedColumns set', () => {
      const customColumns = new Set(['name', 'custom_field'])
      const { query, params } = buildUpdateQuery('devices', customColumns, {
        name: 'Test',
        custom_field: 'value',
      })
      expect(query).toBe('UPDATE devices SET name = ?, custom_field = ? WHERE id = ?')
      expect(params).toEqual(['Test', 'value'])
    })

    it('rejects columns not in custom allowedColumns', () => {
      const customColumns = new Set(['name'])
      expect(() => {
        buildUpdateQuery('devices', customColumns, { name: 'Test', lat: 40.7128 })
      }).toThrow('Invalid column: lat')
    })
  })

  describe('getAllowedColumns', () => {
    it('returns allowed columns for devices', () => {
      const columns = getAllowedColumns('devices')
      expect(columns).toBeInstanceOf(Set)
      expect(columns.has('name')).toBe(true)
      expect(columns.has('lat')).toBe(true)
      expect(columns.has('invalid')).toBe(false)
    })

    it('returns allowed columns for users', () => {
      const columns = getAllowedColumns('users')
      expect(columns.has('role')).toBe(true)
      expect(columns.has('identifier')).toBe(true)
    })

    it('returns allowed columns for pois', () => {
      const columns = getAllowedColumns('pois')
      expect(columns.has('label')).toBe(true)
      expect(columns.has('lat')).toBe(true)
    })

    it('returns empty set for unknown table', () => {
      const columns = getAllowedColumns('unknown')
      expect(columns).toBeInstanceOf(Set)
      expect(columns.size).toBe(0)
    })
  })
})
