import type { FeatureFilters } from '../types';

export interface HexagonLocation {
  lat: number;
  lon: number;
  postcode: string | null;
  resolution: number;
}

const PROPERTY_TYPE_MAP: Record<
  string,
  { rightmove: string; onthemarket: string; zoopla: string }
> = {
  House: { rightmove: 'detached,semi-detached,terraced', onthemarket: 'property', zoopla: '' },
  Detached: { rightmove: 'detached', onthemarket: 'detached', zoopla: 'detached' },
  'Semi-Detached': {
    rightmove: 'semi-detached',
    onthemarket: 'semi-detached',
    zoopla: 'semi_detached',
  },
  'Mid-Terrace': { rightmove: 'terraced', onthemarket: 'terraced', zoopla: 'terraced' },
  'End-Terrace': { rightmove: 'terraced', onthemarket: 'terraced', zoopla: 'terraced' },
  'Enclosed Mid-Terrace': { rightmove: 'terraced', onthemarket: 'terraced', zoopla: 'terraced' },
  'Enclosed End-Terrace': { rightmove: 'terraced', onthemarket: 'terraced', zoopla: 'terraced' },
  Flat: { rightmove: 'flat', onthemarket: 'flats', zoopla: 'flat' },
  Maisonette: { rightmove: 'flat', onthemarket: 'flats', zoopla: 'flat' },
  Bungalow: { rightmove: 'bungalow', onthemarket: 'bungalow', zoopla: 'bungalow' },
  'Park home': { rightmove: 'park-home', onthemarket: 'property', zoopla: '' },
};

export const H3_RADIUS_MILES: Record<number, number> = {
  4: 15,
  5: 6,
  6: 3,
  7: 1,
  8: 0.5,
  9: 0.25,
  10: 0.25,
  11: 0.25,
  12: 0.25,
};

const RIGHTMOVE_RADII = [0.25, 0.5, 1, 3, 5, 10, 15, 20, 30, 40];
const OTM_RADII = [0.25, 0.5, 1, 3, 5, 10, 15, 20, 30, 40];
const ZOOPLA_RADII = [0.25, 0.5, 1, 3, 5, 10, 15, 20, 25, 30];

function nearestRadius(target: number, allowed: number[]): number {
  return allowed.reduce((best, r) => (Math.abs(r - target) < Math.abs(best - target) ? r : best));
}

export function buildPropertySearchUrls(
  location: HexagonLocation,
  filters: FeatureFilters
): { rightmove: string; onthemarket: string; zoopla: string } {
  const { lat, lon, postcode, resolution } = location;
  const radiusMiles = H3_RADIUS_MILES[resolution] ?? 1;
  const coordStr = `${lat.toFixed(5)},${lon.toFixed(5)}`;

  const priceFilter = filters['Last known price'];
  const minPrice =
    Array.isArray(priceFilter) && typeof priceFilter[0] === 'number' ? priceFilter[0] : undefined;
  const maxPrice =
    Array.isArray(priceFilter) && typeof priceFilter[1] === 'number' ? priceFilter[1] : undefined;

  const propertyTypes = filters['Property type'];
  const selectedTypes =
    Array.isArray(propertyTypes) && typeof propertyTypes[0] === 'string'
      ? (propertyTypes as string[])
      : [];

  const rmParams = new URLSearchParams();
  rmParams.set('searchLocation', postcode || coordStr);
  rmParams.set('channel', 'BUY');
  rmParams.set('radius', String(nearestRadius(radiusMiles, RIGHTMOVE_RADII)));
  if (minPrice !== undefined) rmParams.set('minPrice', String(Math.round(minPrice)));
  if (maxPrice !== undefined) rmParams.set('maxPrice', String(Math.round(maxPrice)));
  if (selectedTypes.length > 0) {
    const rmTypes = [
      ...new Set(
        selectedTypes.flatMap((t) => {
          const mapped = PROPERTY_TYPE_MAP[t]?.rightmove;
          return mapped ? mapped.split(',') : [];
        })
      ),
    ];
    if (rmTypes.length > 0) rmParams.set('propertyTypes', rmTypes.join(','));
  }
  const rightmove = `https://www.rightmove.co.uk/property-for-sale/find.html?${rmParams.toString()}`;

  let otmType = 'property';
  if (selectedTypes.length > 0) {
    const otmTypes = [
      ...new Set(selectedTypes.map((t) => PROPERTY_TYPE_MAP[t]?.onthemarket).filter(Boolean)),
    ];
    if (otmTypes.length === 1 && otmTypes[0] !== 'property') otmType = otmTypes[0]!;
  }
  const otmParams = new URLSearchParams();
  otmParams.set('radius', String(nearestRadius(radiusMiles, OTM_RADII)));
  if (minPrice !== undefined) otmParams.set('min-price', String(Math.round(minPrice)));
  if (maxPrice !== undefined) otmParams.set('max-price', String(Math.round(maxPrice)));
  let onthemarket: string;
  if (postcode) {
    const slug = postcode.replace(/\s+/g, '-').toLowerCase();
    onthemarket = `https://www.onthemarket.com/for-sale/${otmType}/${slug}/?${otmParams.toString()}`;
  } else {
    otmParams.set('search-site', 'geo');
    otmParams.set('geo-lat', String(lat));
    otmParams.set('geo-lng', String(lon));
    onthemarket = `https://www.onthemarket.com/for-sale/${otmType}/?${otmParams.toString()}`;
  }

  const zParams = new URLSearchParams();
  zParams.set('q', postcode || coordStr);
  zParams.set('search_source', 'for-sale');
  zParams.set('radius', String(nearestRadius(radiusMiles, ZOOPLA_RADII)));
  if (minPrice !== undefined) zParams.set('price_min', String(Math.round(minPrice)));
  if (maxPrice !== undefined) zParams.set('price_max', String(Math.round(maxPrice)));
  if (selectedTypes.length > 0) {
    const zTypes = [
      ...new Set(selectedTypes.map((t) => PROPERTY_TYPE_MAP[t]?.zoopla).filter(Boolean)),
    ];
    for (const zt of zTypes) {
      zParams.append('property_sub_type', zt!);
    }
  }
  let zoopla: string;
  if (postcode) {
    const slug = postcode.replace(/\s+/g, '-').toLowerCase();
    zoopla = `https://www.zoopla.co.uk/for-sale/property/${slug}/?${zParams.toString()}`;
  } else {
    zParams.set('geo_autocomplete_identifier', `geo_${lat}_${lon}`);
    zoopla = `https://www.zoopla.co.uk/for-sale/property/?${zParams.toString()}`;
  }

  return { rightmove, onthemarket, zoopla };
}
