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

import type { TravelTimeEntry } from '../hooks/useTravelTime';
import { buildTravelParam, dedupeTravelTimeEntries } from './travel-params';

const bankMedian: TravelTimeEntry = {
  mode: 'transit',
  slug: 'bank-tube-station',
  label: 'Bank',
  timeRange: [0, 60],
  useBest: false,
};

describe('travel-params', () => {
  it('deduplicates travel entries by backend key and keeps the tightest range', () => {
    const entries = dedupeTravelTimeEntries([
      bankMedian,
      {
        mode: 'transit',
        slug: 'bank-tube-station',
        label: 'Bank tube station',
        timeRange: [15, 45],
        useBest: false,
      },
      {
        mode: 'walking',
        slug: 'bank-tube-station',
        label: 'Bank',
        timeRange: [0, 20],
        useBest: false,
      },
    ]);

    expect(entries).toEqual([
      {
        mode: 'transit',
        slug: 'bank-tube-station',
        label: 'Bank',
        timeRange: [15, 45],
        useBest: false,
      },
      {
        mode: 'walking',
        slug: 'bank-tube-station',
        label: 'Bank',
        timeRange: [0, 20],
        useBest: false,
      },
    ]);
  });

  it('serializes deduplicated entries before backend requests', () => {
    expect(
      buildTravelParam([
        bankMedian,
        {
          mode: 'transit',
          slug: 'bank-tube-station',
          label: 'Bank',
          timeRange: [10, 50],
          useBest: false,
        },
      ])
    ).toBe('transit:bank-tube-station:10:50');
  });

  it('keeps duplicate blank entries because they are editable placeholders', () => {
    const blank: TravelTimeEntry = {
      mode: 'transit',
      slug: '',
      label: '',
      timeRange: null,
      useBest: false,
    };

    expect(dedupeTravelTimeEntries([blank, blank])).toHaveLength(2);
  });

  it('uses an unbounded range when excluding a deduplicated travel filter', () => {
    expect(
      buildTravelParam(
        [
          bankMedian,
          {
            mode: 'transit',
            slug: 'bank-tube-station',
            label: 'Bank',
            timeRange: [10, 50],
            useBest: false,
          },
        ],
        'tt_transit_bank-tube-station',
        true
      )
    ).toBe('transit:bank-tube-station:0:1440');
  });

  it('encodes transit variants in the mode field when no-change/no-buses are set', () => {
    expect(
      buildTravelParam([
        {
          mode: 'transit',
          slug: 'bank-tube-station',
          label: 'Bank',
          timeRange: [0, 60],
          useBest: false,
          noChange: true,
          noBuses: false,
        },
      ])
    ).toBe('transit-no-change:bank-tube-station:0:60');

    expect(
      buildTravelParam([
        {
          mode: 'transit',
          slug: 'bank-tube-station',
          label: 'Bank',
          timeRange: [0, 60],
          useBest: true,
          noChange: true,
          noBuses: true,
        },
      ])
    ).toBe('transit-no-change-no-bus:bank-tube-station:best:0:60');
  });

  it('keeps different transit variants as separate entries (no dedupe across variants)', () => {
    const transit: TravelTimeEntry = {
      mode: 'transit',
      slug: 'bank-tube-station',
      label: 'Bank',
      timeRange: [0, 90],
      useBest: false,
    };
    const transitNoBus: TravelTimeEntry = {
      ...transit,
      noBuses: true,
    };

    const deduped = dedupeTravelTimeEntries([transit, transitNoBus]);
    expect(deduped).toHaveLength(2);
    expect(buildTravelParam([transit, transitNoBus])).toBe(
      'transit:bank-tube-station:0:90|transit-no-bus:bank-tube-station:0:90'
    );
  });
});
