import {
  GEOCODER,
  getCountryBounds,
  reverseGeocode,
} from "../domain/geocoding";

jest.mock("iso-3166-1");

import iso from "iso-3166-1";

describe("geocoding", () => {
  describe("reverseGeocode", () => {
    it("unpacks reverse geocoding data and returns country", async () => {
      GEOCODER.geocode.mockReturnValue({
        results: [
          {
            address_components: [
              {
                short_name: "us",
                types: ["country"],
              },
            ],
          },
        ],
      });
      expect(await reverseGeocode("test")).toBe("us");
      expect(GEOCODER.geocode).toHaveBeenCalledWith(
        expect.objectContaining({
          location: "test",
        })
      );
    });
    it("handles missing data gracefully", async () => {
      GEOCODER.geocode.mockReturnValue({
        results: [
          {
            address_components: [
              {
                short_name: "md",
                types: ["not-country"],
              },
            ],
          },
        ],
      });
      expect(await reverseGeocode()).toBe(null);
    });
    it("suppresses errors and returns null", async () => {
      GEOCODER.geocode.mockImplementation(() => {
        throw new Error();
      });
      expect(await reverseGeocode()).toBe(null);
    });
  });

  describe("getCountryBounds", () => {
    it("gets bounds for a given country", async () => {
      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
      GEOCODER.geocode.mockReturnValue({
        results: [
          {
            geometry: { viewport: "viewport" },
            types: ["country"],
          },
        ],
      });
      expect(await getCountryBounds("success-test")).toBe("viewport");
      expect(GEOCODER.geocode).toHaveBeenCalledWith(
        expect.objectContaining({
          address: "test-country",
        })
      );
    });
    it("handles missing data gracefully", async () => {
      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
      GEOCODER.geocode.mockReturnValue({
        results: [
          {
            geometry: { viewport: "viewport" },
            types: ["not-country"],
          },
        ],
      });
      expect(await getCountryBounds("bad-data-test")).toBe(null);
    });
    it("suppresses errors and returns null", async () => {
      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
      GEOCODER.geocode.mockImplementation(() => {
        throw new Error();
      });
      expect(await getCountryBounds("error-test")).toBe(null);
    });
    it("uses cache when possible", async () => {
      iso.whereAlpha2.mockReturnValue({ country: "test-country" });
      GEOCODER.geocode.mockReturnValue({
        results: [
          {
            geometry: { viewport: "viewport" },
            types: ["country"],
          },
        ],
      });
      expect(await getCountryBounds("cache-test")).toBe("viewport");
      expect(await getCountryBounds("cache-test")).toBe("viewport");
      expect(GEOCODER.geocode).toHaveBeenCalledTimes(1);
    });
  });
});
