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

import { buildPropertySearchUrls, buildRightmoveExactPostcodeRedirectUrl } from './external-search';

describe('external property search URLs', () => {
  it('returns null when no postcode is available', () => {
    expect(
      buildPropertySearchUrls({
        location: { lat: 51.5, lon: -0.1, resolution: 8 },
        filters: {},
      })
    ).toBeNull();
  });

  it('builds Rightmove, OnTheMarket, and Zoopla URLs with snapped filters', () => {
    const urls = buildPropertySearchUrls({
      location: {
        lat: 51.501,
        lon: -0.141,
        resolution: 8,
        postcode: 'SW1A 1AA',
        isPostcode: false,
      },
      rightmoveLocationId: 'POSTCODE^123456',
      filters: {
        'Last known price': [123_456, 376_000],
        'Property type': ['Detached', 'Flats/Maisonettes'],
        'Leasehold/Freehold': ['Freehold'],
        'Number of bedrooms & living rooms': [2, 4],
      },
    });

    expect(urls).not.toBeNull();
    const rightmove = new URL(urls!.rightmove!);
    const onthemarket = new URL(urls!.onthemarket);
    const zoopla = new URL(urls!.zoopla);

    expect(rightmove.hostname).toBe('www.rightmove.co.uk');
    expect(rightmove.searchParams.get('searchLocation')).toBe('SW1A 1AA');
    expect(rightmove.searchParams.get('locationIdentifier')).toBe('POSTCODE^123456');
    expect(rightmove.searchParams.get('radius')).toBe('0.5');
    expect(rightmove.searchParams.get('minPrice')).toBe('120000');
    expect(rightmove.searchParams.get('maxPrice')).toBe('400000');
    expect(rightmove.searchParams.get('minBedrooms')).toBe('1');
    expect(rightmove.searchParams.get('maxBedrooms')).toBe('3');
    expect(rightmove.searchParams.get('propertyTypes')).toBe('detached,flat');
    expect(rightmove.searchParams.get('tenureTypes')).toBe('FREEHOLD');

    expect(onthemarket.pathname).toBe('/for-sale/property/sw1a-1aa/');
    expect(onthemarket.searchParams.get('radius')).toBe('0.5');
    expect(onthemarket.searchParams.get('min-price')).toBe('120000');
    expect(onthemarket.searchParams.get('max-price')).toBe('400000');
    expect(onthemarket.searchParams.getAll('prop-types')).toEqual(['detached', 'flats']);

    expect(zoopla.searchParams.get('q')).toBe('SW1A 1AA');
    expect(zoopla.searchParams.get('radius')).toBe('0.5');
    expect(zoopla.searchParams.get('price_min')).toBe('100000');
    expect(zoopla.searchParams.get('price_max')).toBe('400000');
    expect(zoopla.searchParams.getAll('property_sub_type')).toEqual(['detached', 'flat']);
  });

  it('omits Rightmove when location identifier is missing and uses minimum radius for other portals', () => {
    const urls = buildPropertySearchUrls({
      location: {
        lat: 51.501,
        lon: -0.141,
        resolution: 9,
        postcode: 'E1 6AN',
        isPostcode: true,
      },
      filters: {},
    });

    expect(urls?.rightmove).toBeNull();
    expect(new URL(urls!.onthemarket).searchParams.get('radius')).toBe('0.25');
    expect(new URL(urls!.zoopla).searchParams.get('radius')).toBe('0.25');
  });

  it('uses Rightmove quarter-mile radius when an exact postcode identifier is provided', () => {
    const urls = buildPropertySearchUrls({
      location: {
        lat: 51.501,
        lon: -0.141,
        resolution: 9,
        postcode: 'SW1A 1AA',
        isPostcode: true,
      },
      rightmoveLocationId: 'POSTCODE^837246',
      filters: {},
    });

    const rightmove = new URL(urls!.rightmove!);

    expect(rightmove.searchParams.get('searchLocation')).toBe('SW1A 1AA');
    expect(rightmove.searchParams.get('locationIdentifier')).toBe('POSTCODE^837246');
    expect(rightmove.searchParams.get('radius')).toBe('0.25');
  });

  it('uses Rightmove outcode-only radius when an outcode identifier is provided', () => {
    const urls = buildPropertySearchUrls({
      location: {
        lat: 51.501,
        lon: -0.141,
        resolution: 8,
        postcode: 'SW1A 1AA',
        isPostcode: false,
      },
      rightmoveLocationId: 'OUTCODE^2506',
      filters: {},
    });

    const rightmove = new URL(urls!.rightmove!);

    expect(rightmove.searchParams.get('locationIdentifier')).toBe('OUTCODE^2506');
    expect(rightmove.searchParams.get('radius')).toBe('0.0');
    expect(new URL(urls!.onthemarket).searchParams.get('radius')).toBe('0.5');
    expect(new URL(urls!.zoopla).searchParams.get('radius')).toBe('0.5');
  });

  it('builds a same-origin Rightmove redirect for exact postcode clicks', () => {
    const target =
      'https://www.rightmove.co.uk/property-for-sale/find.html?searchLocation=SW1A+1AA&locationIdentifier=OUTCODE%5E2506';
    const redirect = new URL(
      buildRightmoveExactPostcodeRedirectUrl('SW1A 1AA', target),
      'https://perfect-postcode.co.uk'
    );

    expect(redirect.pathname).toBe('/api/rightmove-search');
    expect(redirect.searchParams.get('postcode')).toBe('SW1A 1AA');
    expect(redirect.searchParams.get('target')).toBe(target);
  });
});
