import { describe, expect, it } from 'vitest';

import type { FeatureFilters, FeatureMeta } from '../types';
import {
  POI_COUNT_2KM_FILTER_NAME,
  POI_DISTANCE_FILTER_NAME,
  TRANSPORT_DISTANCE_FILTER_NAME,
  clampPoiFilterRange,
  createPoiFilterKey,
  createPoiDistanceFilterKey,
  getActiveAmenityFilterFeatureNames,
  getPoiFilterFeatureOptions,
  getPoiFilterName,
} from './poi-distance-filter';

const numeric = (name: string, overrides: Partial<FeatureMeta> = {}): FeatureMeta => ({
  name,
  type: 'numeric',
  min: 0,
  max: 5,
  ...overrides,
});

describe('poi-distance-filter', () => {
  it('splits public transport distance options out of amenity distance options', () => {
    const features = [
      numeric('Distance to nearest amenity (Cafe) (km)'),
      numeric('Distance to nearest amenity (Park) (km)'),
      numeric('Distance to nearest amenity (Bus stop) (km)'),
      numeric('Distance to nearest amenity (Rail station) (km)'),
    ];

    expect(
      getPoiFilterFeatureOptions(features, POI_DISTANCE_FILTER_NAME).map((f) => f.name)
    ).toEqual([
      'Distance to nearest amenity (Cafe) (km)',
      'Distance to nearest amenity (Park) (km)',
    ]);
    expect(
      getPoiFilterFeatureOptions(features, TRANSPORT_DISTANCE_FILTER_NAME).map((f) => f.name)
    ).toEqual([
      'Distance to nearest amenity (Bus stop) (km)',
      'Distance to nearest amenity (Rail station) (km)',
    ]);
  });

  it('excludes public transport categories from amenity count options', () => {
    const features = [
      numeric('Number of amenities (Cafe) within 2km'),
      numeric('Number of amenities (Bus stop) within 2km'),
      numeric('Number of amenities (Rail station) within 2km'),
    ];

    expect(
      getPoiFilterFeatureOptions(features, POI_COUNT_2KM_FILTER_NAME).map((f) => f.name)
    ).toEqual(['Number of amenities (Cafe) within 2km']);
  });

  it('classifies transport distance features without exposing transport counts', () => {
    expect(getPoiFilterName('Distance to nearest amenity (Bus stop) (km)')).toBe(
      TRANSPORT_DISTANCE_FILTER_NAME
    );
    expect(getPoiFilterName('Number of amenities (Bus stop) within 2km')).toBeNull();
  });

  it('extracts only active non-transport amenity backend feature names', () => {
    const cafeDistance = 'Distance to nearest amenity (Cafe) (km)';
    const parkCount = 'Number of amenities (Park) within 2km';
    const busStopDistance = 'Distance to nearest amenity (Bus stop) (km)';
    const filters: FeatureFilters = {
      [createPoiDistanceFilterKey(cafeDistance, 0)]: [0, 1],
      [createPoiFilterKey(POI_COUNT_2KM_FILTER_NAME, parkCount, 1)]: [2, 10],
      [createPoiFilterKey(TRANSPORT_DISTANCE_FILTER_NAME, busStopDistance, 2)]: [0, 0.5],
      Price: [0, 500000],
    };

    expect([...getActiveAmenityFilterFeatureNames(filters)]).toEqual([cafeDistance, parkCount]);
  });

  it('clamps fixed amenity distance scales to the 0-5km slider bounds', () => {
    const feature = numeric('Distance to nearest amenity (Cafe) (km)', {
      absolute: true,
      histogram: { min: 0.2, max: 12, p1: 0.3, p99: 9, counts: [1, 2, 3] },
    });

    expect(clampPoiFilterRange([-1, 8], feature)).toEqual([0, 5]);
  });
});
