import axios from "axios";
import NominatimQuery from "../../utils/nominatimQuery";
import NominatimResponse from "../../utils/nominatimResponse";
import ShortMapPointsResponse from "../../utils/shortMapPointsResponse";
import PointType from "../../utils/pointsType";
import FullMapPointsQuery from "../../utils/fullMapPointsQuery";
import _ from "lodash";
import OSMNamesResponse from "../../utils/osmNamesResponse";
import OSMNamesQuery from "../../utils/osmNamesQuery";
import PointsAutocompleteQuery from "../../utils/pointsAutocompleteQuery";
import FullMapPointsResponse from "../../utils/fullMapPointsResponse";
import FullNominatimResponse from "../../utils/fullNominatimResponse";

class EpakaApi {
  s_pointFileIndex = [];

  async getPointsFilesIndexes() {
    try {
      const response = await axios.get(
        "/wp-json/epaka-public/get-points-files-indexes",
      );
      this.s_pointFileIndex = response.data;
    } catch (e) {
      console.log(e);
    }
  }

  async getPointsFromFile(courier, country, selectedPointId, options) {
    try {
      if (this.s_pointFileIndex.length === 0) {
        await this.getPointsFilesIndexes();
      }

      let prefix = "";
      if (country !== "PL") {
        prefix = country + "_";
      }

      const suffixes = [];
      if (options.function === "nadanie") {
        suffixes.push("_n");
      } else {
        suffixes.push("_o");
      }
      if (options.cod_only) {
        suffixes.push("_cod");
      }
      if (options.weight > 20) {
        suffixes.push("_o20");
      }

      let filenameWithSuffixes = prefix + courier + suffixes.join("");
      while (
        this.s_pointFileIndex.find(
          (element) => element === filenameWithSuffixes,
        ) === undefined &&
        suffixes.length
      ) {
        suffixes.pop();
        filenameWithSuffixes = prefix + courier + suffixes.join("");
      }

      if (
        this.s_pointFileIndex.find(
          (element) => element === filenameWithSuffixes,
        ) === undefined
      ) {
        // jeśli nie ma na liście pliku z punktami dla wybranego kuriera to ustaw punkty epaki
        filenameWithSuffixes = "0";
        if (prefix !== "") {
          return [];
        }
      }

      let response = await axios.get(
        "/wp-json/epaka-public/get-points-file?filenameWithSuffixes=" +
          filenameWithSuffixes,
      );

      let mapPoints = [];
      response.data.forEach((el) => {
        const point = new ShortMapPointsResponse(el);
        if (point.point_id === selectedPointId) {
          mapPoints.push(point);
        } else {
          if (options.onlyEpaka) {
            if ([11, 50, 4].includes(courier)) {
              if (point.type === PointType.PointAndEpaka) {
                mapPoints.push(point);
              }
            } else {
              if (
                point.type === PointType.PointAndEpaka ||
                point.type === PointType.Epaka
              ) {
                mapPoints.push(point);
              }
            }
          } else {
            if (point.type === PointType.Point && options.showPoints) {
              mapPoints.push(point);
            }
            if (point.type === PointType.Machine && options.showMachines) {
              mapPoints.push(point);
            }
            if (
              point.type === PointType.PointAndEpaka ||
              (point.type === PointType.Epaka && !options.onlyMachines)
            ) {
              mapPoints.push(point);
            }
          }
        }
      });

      return mapPoints;
    } catch (e) {
      console.log(e);
      return [];
    }
  }

  async getFullPointsDataByLatLngProximity(
    courier,
    country,
    latlng,
    options,
    selectedPointId,
  ) {
    try {
      const defaultOptions = {
        cod_only: false,
        function: "odbior",
        weight: 1,
        onlyEpaka: false,
        onlyMachines: false,
        zoom: 0,
        showMachines: true,
        showPoints: true,
      };
      const mergedOptions = { ...defaultOptions, ...options };

      const params = new FullMapPointsQuery();
      params.courier = courier;
      params.country = country;
      params.latlng = latlng;
      params.cod_only = mergedOptions.cod_only;
      params.function = mergedOptions.function;
      params.weight = mergedOptions.weight;
      params.withoutPrinter = mergedOptions?.onlyEpaka;
      params.zoom = mergedOptions.zoom;
      params.onlyMachines = mergedOptions.onlyMachines;
      params.showMachines = mergedOptions.showMachines;
      params.showPoints = mergedOptions.showPoints;
      params.selectedPointId = selectedPointId;

      const response = await axios.post(
        "/wp-json/epaka-public/get-full-points-data-by-lat-lng-proximity",
        params,
      );

      return (
        response.data ?? {
          bbox: [],
          points: [],
        }
      );
    } catch (e) {
      console.log(e);
      return {
        bbox: [],
        points: [],
      };
    }
  }

  async getNominatimSearch(query, countrycodes = "PL", limit = 3) {
    try {
      const postcode = /([0-9]{2}-[0-9]{3})|([0-9]{5})/;
      const params = new NominatimQuery();
      params.countrycodes = countrycodes;
      params.limit = limit;

      if (postcode.test(query)) {
        params.postalcode = postcode.exec(query)[0];
      } else {
        params.q = query;
      }

      const response = await axios.get(
        "/wp-json/epaka-public/get-nominatim-search" + params.toString(),
      );

      let nominatim = [];

      response.data.forEach((el) => {
        nominatim.push(new NominatimResponse(el));
      });

      return nominatim;
    } catch (e) {
      console.log(e);
      return [];
    }
  }

  async getFullNominatimSearch(query, countrycodes = "PL", limit = 3) {
    const postcode = /([0-9]{2}-[0-9]{3})|([0-9]{5})/;
    const params = new NominatimQuery();
    params.countrycodes = countrycodes;
    params.limit = limit;

    if (postcode.test(query)) {
      params.postalcode = postcode.exec(query)[0];
    } else {
      params.q = query;
    }

    const response = await axios.get(
      "/wp-json/epaka-public/get-nominatim-search" + params.toString(),
    );

    let nominatim = [];

    if (_.isArray(response.data)) {
      response.data.forEach((el) => {
        nominatim.push(new FullNominatimResponse(el));
      });

      nominatim = nominatim.filter((value, index, array) => {
        const found = array.findIndex(
          (element) => element.processed_name === value.processed_name,
        );
        return found === index;
      });

      return nominatim;
    }
    return [];
  }

  async getAddressAutocomplete(query, countrycodes = "PL", limit = 3) {
    const params = new OSMNamesQuery();
    params.countrycodes = countrycodes;
    params.count = limit * 2;
    if (params.count < 10) params.count = 10;

    params.q = query.replaceAll("(", "").replaceAll(")", "");

    const response = await axios.get(
      "/wp-json/epaka-public/get-nominatim-search" + params.toString(),
    );

    let nominatim = [];

    if (response.data.results !== undefined) {
      response.data?.results.forEach((el) => {
        nominatim.push(new OSMNamesResponse(el));
      });
    }

    nominatim = nominatim.filter((value, index, array) => {
      const found = array.findIndex(
        (element) => element.processed_name === value.processed_name,
      );
      return found === index;
    });

    return nominatim.slice(0, limit);
  }

  async requestPointsAutocomplete(
    query,
    courier,
    limit = 5,
    options = {
      cod_only: false,
      weight: 1,
      function: "nadanie",
      withoutPrinter: false,
    },
  ) {
    const params = new PointsAutocompleteQuery();
    params.courier = courier;
    params.q = query;
    params.cod_only = options.cod_only;
    params.function = options.function;
    params.weight = options.weight;
    params.withoutPrinter = options.withoutPrinter;
    params.limit = limit;

    const response = await axios.get(
      "/wp-json/epaka-public/get-points-autocomplete" + params.toString(),
    );

    let mapPoints = [];

    response.data?.forEach((el) => {
      mapPoints.push(new FullMapPointsResponse(el));
    });

    return mapPoints;
  }
}

export default EpakaApi;
