import { getGeolocationForIpAddress } from "fastly:geolocation";
import { ConfigStore } from "fastly:config-store";

const handler = async (event) => {
  // Get the request from the client
  const req = event.request;

  try {
    let ip = new URL(req.url).searchParams.get("ip") || event.client.address;
    let geo = getGeolocationForIpAddress(ip);
    let latitude = 0.0;
    let longitude = 0.0;

    if (geo) {
      // Connect to config store
      const configStore = new ConfigStore("region_defs");
      // Get country code
      let countryCode = geo.country_code;
      // Get country's region info from ConfigStore
      const region =
        configStore.get(countryCode) ||
        configStore.get("_default") ||
        "blocked";

      console.log(`Country: ${countryCode}, Region: ${region}`);

      // Block the request if the region is set as "blocked"
      if (region === "blocked") {
        return new Response(
          "Sorry, our service is currently not available in your region",
          {
            status: 403,
          }
        );
      }

      // Set country/region/cotinent information on request header
      const continent = geo.continent;
      req.headers.set("client-geo-country", countryCode);
      req.headers.set("client-geo-region", region);
      req.headers.set("client-geo-continent", continent);

      console.log(`Continent: ${continent}`);

      // Get latitude and longtitude from Fastly Geo API
      latitude = geo.latitude;
      longitude = geo.longitude;
    }

    // Get latitude and longtitude from cookie,
    // if info exists in cookie, will overwrite what we got from Fastly GEO API
    const cookieGeo = getCookieGeo(req);

    if (cookieGeo) {
      [latitude, longitude] = cookieGeo;
    }

    req.headers.set(
      "client-geo-latlng",
      `${latitude.toFixed(1)}, ${longitude.toFixed(1)}`
    );
    console.log(`Lat:${latitude}, Lng: ${longitude}`);

    const beresp = await fetch(req, {
      backend: "origin_0",
    });

    // Send our response back to the client.
    return beresp;
  } catch (error) {
    console.error(error);
    return new Response("Internal Server Error", {
      status: 500,
    });
  }
};

addEventListener("fetch", (event) => event.respondWith(handler(event)));

function getCookieGeo(req) {
  const cookieVal = req.headers.get("cookie");

  if (!cookieVal) {
    return null;
  }

  const geoString = cookieVal
    .split(";")
    .find((kv) => kv.trim().startsWith("client-geo-latlng="));

  if (!geoString) {
    return null;
  }

  const [, value] = geoString.split("=");
  const geo = decodeURIComponent(value);
  const geoMatch = /^([0-9.]+),\s*([0-9.]+)$/.exec(geo);

  if (!geoMatch) {
    return null;
  }

  const latitude = parseFloat(geoMatch[1]);
  const longitude = parseFloat(geoMatch[2]);

  return [latitude, longitude];
}