import { describe, it, expect } from 'vitest'
import { geojsonFeatures } from './geojson-features'
import type { FeatureData } from './types'

describe('geojsonFeatures', () => {
  it('should return features unchanged when uniqueIdProperty is not provided', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1' },
      },
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [1, 1] },
        properties: { name: 'Feature 2' },
      },
    ]

    const result = geojsonFeatures({ geojson: features })

    expect(result).toHaveLength(2)
    expect(result[0]?.properties).toEqual({ name: 'Feature 1', id: '' })
    expect(result[1]?.properties).toEqual({ name: 'Feature 2', id: '' })
  })

  it('should preserve existing properties when uniqueIdProperty exists', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', customId: 'abc123' },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'customId',
    })

    expect(result[0]?.properties).toEqual({
      name: 'Feature 1',
      customId: 'abc123',
    })
  })

  it('should add id property when uniqueIdProperty is provided and exists', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', customId: 'abc123' },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'customId',
    })

    expect(result[0]?.properties).toHaveProperty('customId', 'abc123')
  })

  it('should add stringified undefined id when uniqueIdProperty does not exist in properties', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1' },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'customId',
    })

    expect(result[0]?.properties).toEqual({
      name: 'Feature 1',
      id: 'undefined',
    })
  })

  it('should handle features without properties', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: {},
      },
    ]

    const result = geojsonFeatures({ geojson: features })

    expect(result[0]?.properties).toEqual({ id: '' })
  })

  it('should handle null properties', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: null,
      },
    ]

    const result = geojsonFeatures({ geojson: features })

    expect(result[0]?.properties).toEqual({ id: '' })
  })

  it('should convert uniqueIdProperty value to string', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', numericId: 12345 },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'numericId',
    })

    expect(result[0]?.properties).toHaveProperty('numericId', 12345)
  })

  it('should handle undefined uniqueIdProperty value', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', customId: undefined },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'customId',
    })

    expect(result[0]?.properties).toEqual({
      name: 'Feature 1',
      customId: undefined,
      id: 'undefined',
    })
  })

  it('should handle null uniqueIdProperty value', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', customId: null },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'customId',
    })

    expect(result[0]?.properties).toEqual({
      name: 'Feature 1',
      customId: null,
      id: 'null',
    })
  })

  it('should preserve geometry data', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: {
          type: 'Polygon',
          coordinates: [
            [
              [0, 0],
              [1, 0],
              [1, 1],
              [0, 1],
              [0, 0],
            ],
          ],
        },
        properties: { name: 'Polygon 1' },
      },
    ]

    const result = geojsonFeatures({ geojson: features })

    expect(result[0]?.geometry).toEqual(features[0]?.geometry)
    expect(result[0]?.type).toBe('Feature')
  })

  it('should process multiple features with different properties', () => {
    const features: FeatureData[] = [
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [0, 0] },
        properties: { name: 'Feature 1', uid: 'id1' },
      },
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [1, 1] },
        properties: { name: 'Feature 2', uid: 'id2' },
      },
      {
        type: 'Feature',
        geometry: { type: 'Point', coordinates: [2, 2] },
        properties: { name: 'Feature 3' },
      },
    ]

    const result = geojsonFeatures({
      geojson: features,
      uniqueIdProperty: 'uid',
    })

    expect(result).toHaveLength(3)
    expect(result[0]?.properties).toHaveProperty('uid', 'id1')
    expect(result[1]?.properties).toHaveProperty('uid', 'id2')
    expect(result[2]?.properties).toEqual({
      name: 'Feature 3',
      id: 'undefined',
    })
  })

  it('should handle empty array', () => {
    const result = geojsonFeatures({ geojson: [] })
    expect(result).toEqual([])
  })
})
