/*
Rent a flat
Web:
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-mieten?numberofrooms=1.0-10000.0&price=1.0-10000.0&livingspace=10.0-10000.0&pricetype=rentpermonth&enteredFrom=result_list
*/

/*
Rent a flat:
Web:
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-mieten?enteredFrom=one_step_search
Mobile:
https://api.mobile.immobilienscout24.de/search/list?numberofrooms=1.5-&searchId=d7c127d8-6630-49e8-a1dd-5ae04dad454d&sorting=standard&pagesize=20&livingspace=10-500&pagenumber=1&realestatetype=apartmentrent&priceType=calculatedtotalrent&price=1-10000&publishedafter=2025-05-14T09:11:54&channel=is24&searchType=region&geocodes=/de/nordrhein-westfalen/duesseldorf&features=adKeysAndStringValues,virtualTour,contactDetails,viareporting,nextgen,calculatedTotalRent,listingsInListFirstSummary,xxlListingType,quickfilters,grouping,projectsInAllRealestateTypes,fairPrice
*/

/*
Rent a house:
Web:
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/haus-mieten?enteredFrom=one_step_search
Mobile:
https://api.mobile.immobilienscout24.de/search/map/v3?publishedafter=2025-05-14T09:12:49&pagenumber=1&searchType=region&geocodes=/de/nordrhein-westfalen/duesseldorf&realEstateType=houserent&pagesize=300&features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&sorting=standard
*/

/*
 buy a flat
 Web:
 https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0&livingspace=1.0-10000.0&enteredFrom=result_list
 Mobile:
 https://api.mobile.immobilienscout24.de/search/map/v3?features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&sorting=standard&realEstateType=apartmentbuy&pagesize=300&pagenumber=1&geocodes=/de/nordrhein-westfalen/duesseldorf&publishedafter=2025-05-14T09:14:43&searchType=region
 */

/*
 Buy a house
 Web:
 https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/haus-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0E7&livingspace=1.0-10000.0&enteredFrom=result_list
 Mobile:
 https://api.mobile.immobilienscout24.de/search/map/v3?geocodes=/de/nordrhein-westfalen/duesseldorf&features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&searchType=region&realEstateType=housebuy&pagenumber=1&pagesize=300&sorting=standard&publishedafter=2025-05-14T09:16:28
 */

/*
 Buy a house only in parts of a city
 Web:
 https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/haus-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0E7&livingspace=1.0-10000.0&geocodes=1276010037,1276010014,1276010012&enteredFrom=result_list
 Mobile:
 https://api.mobile.immobilienscout24.de/search/list?pagesize=20&pagenumber=1&features=adKeysAndStringValues,virtualTour,contactDetails,viareporting,grouping,nextgen,listingsInListFirstSummary,xxlListingType,quickfilters,fairPrice&sorting=standard&channel=is24&geocodes=/de/nordrhein-westfalen/duesseldorf/stadtbezirk-1&searchType=region&realestatetype=housebuy&publishedafter=2025-05-14T09:17:23
 */

/*
 Buy a house with radius
 Web:
 https://www.immobilienscout24.de/Suche/radius/haus-kaufen?centerofsearchaddress=D%C3%BCsseldorf%3B%3B%3B%3B%3B%3B&numberofrooms=1.0-10000.0&price=1.0-1.0E7&livingspace=1.0-10000.0&geocoordinates=51.22496%3B6.77567%3B5.0&enteredFrom=result_list
 Mobile:
 https://api.mobile.immobilienscout24.de/home/search/total?pagenumber=1&pagesize=1&geocoordinates=51.224960;6.775670;4.0&sorting=standard&searchType=radius&features=adKeysAndStringValues,virtualTour,contactDetails,grouping,nextgen,listingsInListFirstSummary,xxlListingType,fairPrice&channel=is24&realestatetype=housebuy&publishedafter=2025-05-14T09:19:43
 */

/*
 Buy a house with shape
 Web:
 https://www.immobilienscout24.de/Suche/shape/haus-kaufen?shape=eW1yd0hpZGloQGBJa1NfQWFsQG9Uc1ZvVmlDbHdAZ2BAaEBjfEB5U3NWY2NCa0RvWmpwQG1KYGdCeldqU3Z4QGBAbENvQmJWaGtA&numberofrooms=1.0-100000.0&price=1.0-1.0E7&livingspace=1.0-100000.0&enteredFrom=result_list#/
 Mobile:
 https://api.mobile.immobilienscout24.de/search/map/v3?features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&publishedafter=2025-05-14T09:19:43&sorting=standard&pagesize=300&searchType=shape&realEstateType=housebuy&pagenumber=1&shape=%7D%7BjwHy%7Cqh@jCKdCgAvB_BdB%7DBzAaCjAqCfAqC~@uCt@iCh@eCZkCLyC?_EO%7DEa@%7DEa@iE_@%7BD%5DaDe@gDi@gDo@uCu@kBcB_AeDOiE?iDCgCMuBOkDCkG?yFRgD%60@cB%5C%7BA%60@eBx@aB%7C@kAbAy@rAe@bBUxCAhE?dFh@fGlAzGbBbHlBxGdB%60FrAhDz@xBh@nAf@l@RNNXkCkMJR~B%7CEnCpErCnDtClCvC~ApCh@rCJpC?
 */
import queryString from 'query-string';
import { nullOrEmpty } from '../../utils.js';

const PARAM_NAME_MAP = {
  heatingtypes: 'heatingtypes',
  haspromotion: 'haspromotion',
  numberofrooms: 'numberofrooms',
  livingspace: 'livingspace',
  energyefficiencyclasses: 'energyefficiencyclasses',
  exclusioncriteria: 'exclusioncriteria',
  equipment: 'equipment',
  petsallowedtypes: 'petsallowedtypes',
  price: 'price',
  constructionyear: 'constructionyear',
  apartmenttypes: 'apartmenttypes',
  pricetype: 'pricetype',
  floor: 'floor',
  geocodes: 'geocodes',
  geocoordinates: 'geocoordinates',
  shape: 'shape',
  sorting: 'sorting',
  newbuilding: 'newbuilding',
};

const EQUIPMENT_MAP = {
  parking: 'parking',
  cellar: 'cellar',
  builtinkitchen: 'builtInKitchen',
  lift: 'lift',
  garden: 'garden',
  guesttoilet: 'guestToilet',
  balcony: 'balcony',
  handicappedaccessible: 'handicappedAccessible',
};

const REAL_ESTATE_TYPE = {
  'haus-mieten': 'houserent',
  'wohnung-mieten': 'apartmentrent',
  'wohnung-kaufen': 'apartmentbuy',
  'haus-kaufen': 'housebuy',
};

const WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP = {
  // Category "Balkon/Terrasse"
  'wohnung-mit-balkon-mieten': { equipment: ['balcony'] },
  'wohnung-mit-garten-mieten': { equipment: ['garden'] },
  // Category "Wohnungstyp"
  'souterrainwohnung-mieten': { apartmenttypes: ['halfbasement'] },
  'erdgeschosswohnung-mieten': { apartmenttypes: ['groundfloor'] },
  'hochparterrewohnung-mieten': { apartmenttypes: ['raisedgroundfloor'] },
  'etagenwohnung-mieten': { apartmenttypes: ['apartment'] },
  'loft-mieten': { apartmenttypes: ['loft'] },
  'maisonette-mieten': { apartmenttypes: ['maisonette'] },
  'terrassenwohnung-mieten': { apartmenttypes: ['terracedflat'] },
  'penthouse-mieten': { apartmenttypes: ['penthouse'] },
  'dachgeschosswohnung-mieten': { apartmenttypes: ['roofstorey'] },
  // Category "Ausstattung"
  'wohnung-mit-garage-mieten': { equipment: ['parking'] },
  'wohnung-mit-einbaukueche-mieten': { equipment: ['builtinkitchen'] },
  'wohnung-mit-keller-mieten': { equipment: ['cellar'] },
  // Category "Merkmale"
  'neubauwohnung-mieten': { newbuilding: true },
  'barrierefreie-wohnung-mieten': { equipment: ['handicappedaccessible'] },
};

export function convertWebToMobile(webUrl) {
  let url;
  try {
    url = new URL(webUrl);
  } catch {
    throw new Error(`Invalid URL: ${webUrl}`);
  }

  const segments = url.pathname.split('/');
  if (segments[1] !== 'Suche') {
    throw new Error(`Unexpected path format: ${url.pathname}. We're expecting to see "/Suche" in the path.`);
  }

  const realTypeKey = segments.at(-1);
  let realType = REAL_ESTATE_TYPE[realTypeKey];
  let additionalParamsFromWebPath;

  if (!realType) {
    // Test for seo optimized apartment path (only used on the ImmoScout web app)
    if (WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey]) {
      additionalParamsFromWebPath = WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey];
      realType = REAL_ESTATE_TYPE['wohnung-mieten'];
    } else {
      throw new Error(`Real estate type not found: ${realTypeKey}`);
    }
  }

  if (segments.includes('shape')) {
    throw new Error('Shape is currently not supported using Immoscout');
  }

  const { query: rawParams } = queryString.parseUrl(webUrl, { arrayFormat: 'comma' });
  const webParams = Object.fromEntries(
    Object.entries(rawParams).filter(([key]) => key !== 'enteredFrom' && PARAM_NAME_MAP[key]),
  );

  const geocodes = `/${segments.slice(2, 5).join('/')}`;
  const isRadius = segments.includes('radius');
  const mobileParams = {
    searchType: isRadius ? 'radius' : 'region',
    realestatetype: realType,
    ...(isRadius ? {} : { geocodes }),
    ...additionalParamsFromWebPath,
  };

  if (webParams.geocoordinates) {
    mobileParams.geocoordinates = webParams.geocoordinates;
  }

  for (const [key, val] of Object.entries(webParams)) {
    if (key === 'equipment') {
      const items = [].concat(val).flatMap((v) => `${v}`.split(','));
      const currentEquipmentParams = mobileParams[PARAM_NAME_MAP[key]];
      mobileParams[PARAM_NAME_MAP[key]] = [
        ...(currentEquipmentParams ?? []),
        ...items.map((item) => EQUIPMENT_MAP[item.toLowerCase()]).filter(Boolean),
      ];
    } else {
      mobileParams[PARAM_NAME_MAP[key]] = val;
    }
  }

  const mobileQuery = queryString.stringify(mobileParams, {
    arrayFormat: 'comma',
    encode: true,
    skipEmptyString: true,
  });

  return `https://api.mobile.immobilienscout24.de/search/list?${mobileQuery}`;
}

export function convertImmoscoutListingToMobileListing(url) {
  if (nullOrEmpty(url)) {
    return null;
  }

  return url.replace(
    /^https:\/\/www\.immobilienscout24\.de\/expose\//,
    'https://api.mobile.immobilienscout24.de/expose/',
  );
}
