import { describe, it, expect } from 'vitest'
import { mappingLegendMeridian } from './mapping-meridian'
import type { Layer } from '../providers/layers/types'

interface LegendLayerData {
  /** id of the layer */
  id: string
  /** title of the layer to show in the legend */
  title?: string
  /** layer visibility state */
  visible?: boolean
  /** whether layer visibility state can be toggled on/off */
  switchable?: boolean
  /** layer collapsed state */
  collapsed?: boolean
  /** whether layer collapsed state can be toggled on/off */
  collapsible?: boolean
  /** layer opacity percentage */
  opacity?: number
  /** whether layer opacity percentage can be modified */
  showOpacityControl?: boolean
  /** note to show below all legend items */
  helperText?: React.ReactNode
  /** min zoom at which layer is displayed */
  minZoom?: number
  /** max zoom at which layer is displayed */
  maxZoom?: number
  /** object or array containing the legend part(s) display settings */
  legend?: unknown[]
}

describe('mappingLegendMeridian', () => {
  it('should map layer to meridian format with all properties', () => {
    const layer: Layer = {
      props: {
        id: 'test-layer',
        opacity: 0.8,
        visible: true,
      },
      name: 'Test Layer',
      legend: {
        collapsed: false,
        collapsible: true,
        helperText: 'Helper text',
        variables: [{ id: 'var1', label: 'Variable 1' }],
        maxZoom: 20,
        minZoom: 5,
        opacityControl: true,
        switchable: true,
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result).toEqual({
      collapsed: false,
      collapsible: true,
      helperText: 'Helper text',
      id: 'test-layer',
      legend: [{ id: 'var1', label: 'Variable 1' }],
      maxZoom: 20,
      minZoom: 5,
      opacity: 0.8,
      showOpacityControl: true,
      switchable: true,
      title: 'Test Layer',
      visible: true,
    })
  })

  it('should use default opacity of 1 when not provided', () => {
    const layer: Layer = {
      props: {
        id: 'test-layer',
      },
      name: 'Test Layer',
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.opacity).toBe(1)
  })

  it('should use default visible of true when not provided', () => {
    const layer: Layer = {
      props: {
        id: 'test-layer',
      },
      name: 'Test Layer',
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.visible).toBe(true)
  })

  it('should handle layer with minimal properties', () => {
    const layer: Layer = {
      props: {
        id: 'minimal-layer',
      },
      name: 'Minimal Layer',
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result).toEqual({
      collapsed: undefined,
      collapsible: undefined,
      helperText: undefined,
      id: 'minimal-layer',
      legend: undefined,
      maxZoom: undefined,
      minZoom: undefined,
      opacity: 1,
      showOpacityControl: undefined,
      switchable: undefined,
      title: 'Minimal Layer',
      visible: true,
    })
  })

  it('should handle layer with visible: false', () => {
    const layer: Layer = {
      props: {
        id: 'invisible-layer',
        visible: false,
      },
      name: 'Invisible Layer',
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.visible).toBe(false)
  })

  it('should handle layer with opacity: 0', () => {
    const layer: Layer = {
      props: {
        id: 'transparent-layer',
        opacity: 0,
      },
      name: 'Transparent Layer',
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.opacity).toBe(0)
  })

  it('should map legend variables correctly', () => {
    const layer: Layer = {
      props: {
        id: 'layer-with-variables',
      },
      name: 'Layer with Variables',
      legend: {
        variables: [
          { id: 'var1', label: 'Variable 1', color: '#ff0000' },
          { id: 'var2', label: 'Variable 2', color: '#00ff00' },
        ],
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.legend).toHaveLength(2)
    expect(result.legend).toEqual([
      { id: 'var1', label: 'Variable 1', color: '#ff0000' },
      { id: 'var2', label: 'Variable 2', color: '#00ff00' },
    ])
  })

  it('should handle zoom level constraints', () => {
    const layer: Layer = {
      props: {
        id: 'zoom-constrained-layer',
      },
      name: 'Zoom Constrained Layer',
      legend: {
        minZoom: 10,
        maxZoom: 18,
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.minZoom).toBe(10)
    expect(result.maxZoom).toBe(18)
  })

  it('should handle collapsed and collapsible properties', () => {
    const layer: Layer = {
      props: {
        id: 'collapsible-layer',
      },
      name: 'Collapsible Layer',
      legend: {
        collapsed: true,
        collapsible: false,
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.collapsed).toBe(true)
    expect(result.collapsible).toBe(false)
  })

  it('should handle switchable property', () => {
    const layer: Layer = {
      props: {
        id: 'switchable-layer',
      },
      name: 'Switchable Layer',
      legend: {
        switchable: false,
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.switchable).toBe(false)
  })

  it('should map empty legend variables array', () => {
    const layer: Layer = {
      props: {
        id: 'empty-variables-layer',
      },
      name: 'Empty Variables Layer',
      legend: {
        variables: [],
      },
      type: null,
    }

    const result = mappingLegendMeridian<LegendLayerData>(layer)

    expect(result.legend).toEqual([])
  })
})
