import { describe, it, expect } from 'vitest'
import { buildQueryKey } from './build-query-key'
import type { Source } from '../../providers/sources/types'

describe('buildQueryKey', () => {
  const queryKeyPrefix = ['categories']

  it('returns [sourceId, ...prefix] when source is undefined', () => {
    const key = buildQueryKey(queryKeyPrefix, 'src1', undefined)
    expect(key).toEqual(['src1', 'categories'])
  })

  it('appends string data when present', () => {
    const source = {
      id: 'src1',
      type: 'query',
      data: 'SELECT * FROM t',
      connectionName: 'conn',
    } as unknown as Source
    const key = buildQueryKey(queryKeyPrefix, 'src1', source)
    expect(key).toEqual(['src1', 'categories', 'SELECT * FROM t'])
  })

  it('appends a stable fingerprint object for geojson array data', () => {
    const features = [
      { type: 'Feature', geometry: null, properties: { id: 1 } },
      { type: 'Feature', geometry: null, properties: { id: 2 } },
      { type: 'Feature', geometry: null, properties: { id: 3 } },
    ]
    const source = {
      id: 'src1',
      type: 'geojson',
      data: features,
    } as unknown as Source
    const key = buildQueryKey(queryKeyPrefix, 'src1', source)
    const fingerprint = key[2] as string
    expect(typeof fingerprint).toBe('string')
    const parsed = JSON.parse(fingerprint) as Record<string, unknown>
    expect(parsed).toMatchObject({
      type: 'geojson',
      length: 3,
      first: features[0],
      last: features[2],
    })
  })

  it('appends queryParameters serialized as JSON', () => {
    const source = {
      id: 'src1',
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      queryParameters: { limit: 100 },
    } as unknown as Source
    const key = buildQueryKey(queryKeyPrefix, 'src1', source)
    expect(key.at(-1)).toBe(JSON.stringify({ limit: 100 }))
  })

  it('appends a serialized representation of authorization/cache-control headers', () => {
    const source = {
      id: 'src1',
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      headers: {
        Authorization: 'Bearer token',
        'X-Ignored': 'nope',
      },
    } as unknown as Source
    const key = buildQueryKey(queryKeyPrefix, 'src1', source)
    const last = key.at(-1) as string
    expect(typeof last).toBe('string')
    expect(last).toContain('authorization')
    expect(last).toContain('Bearer token')
    expect(last).not.toContain('x-ignored')
  })

  it('omits headers entry when no relevant headers present', () => {
    const source = {
      id: 'src1',
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      headers: { 'X-Ignored': 'nope' },
    } as unknown as Source
    const key = buildQueryKey(queryKeyPrefix, 'src1', source)
    expect(key).toEqual(['src1', 'categories', 'SELECT 1'])
  })

  it('produces a stable result for identical inputs', () => {
    const source = {
      id: 'src1',
      type: 'query',
      data: 'SELECT 1',
      connectionName: 'conn',
      queryParameters: { limit: 100 },
    } as unknown as Source
    const a = buildQueryKey(queryKeyPrefix, 'src1', source)
    const b = buildQueryKey(queryKeyPrefix, 'src1', source)
    expect(a).toEqual(b)
  })
})
