import {
  formatEntry,
  getEntry,
  getEntryById,
  getEntryByPosition,
  getFirstEntry,
  getHomeScreenId,
  getTypeMappedScreen,
  queryIsValid,
} from "../useOpenSchemeHandler/utils";

describe("queryIsValid", () => {
  describe("when query has a type", () => {
    const query = { type: "some_type" };

    it("returns true", () => {
      expect(queryIsValid(query)).toBe(true);
    });
  });

  describe("when query has a screen_id", () => {
    const query = { screen_id: "some_screen_id" };

    it("returns true", () => {
      expect(queryIsValid(query)).toBe(true);
    });
  });

  describe("when query has a feed_locator", () => {
    const query = { feed_locator: "some_feed_locator" };

    it("returns true", () => {
      expect(queryIsValid(query)).toBe(true);
    });
  });

  describe("when query has no type, no screen_id, no feed_locator", () => {
    const query = { param: "value" };

    it("returns false", () => {
      expect(queryIsValid(query)).toBe(false);
    });
  });
});

describe("getTypeMappedScreen", () => {
  const existingScreenType = "existing_screen";
  const notExistingScreenType = "not_existing_screen";

  const contentTypes: ZappContentTypes = {
    [existingScreenType]: {
      screen_id: "A1234",
    },
    [notExistingScreenType]: {
      screen_id: "C0987",
    },
  };

  const rivers: Record<string, Partial<ZappRiver>> = {
    A1234: {
      id: "A1234",
    },
    B5678: {
      id: "B5678",
    },
  };

  describe("when type exists in contentTypes", () => {
    expect(
      getTypeMappedScreen(existingScreenType, rivers, contentTypes)
    ).toEqual(rivers.A1234);
  });

  describe("when type does not exist in contentTypes", () => {
    expect(getTypeMappedScreen("unknown_type", rivers, contentTypes)).toBe(
      null
    );
  });

  describe("when target screen exists", () => {
    expect(
      getTypeMappedScreen(existingScreenType, rivers, contentTypes)
    ).toEqual(rivers.A1234);
  });

  describe("when target screen doesn't exists", () => {
    expect(
      getTypeMappedScreen(notExistingScreenType, rivers, contentTypes)
    ).toBe(null);
  });
});

describe("resolving entries", () => {
  const entries: ZappEntry[] = [
    { id: "entry_1", type: { value: "show" } },
    { id: "entry_2", type: { value: "video" } },
    { id: "entry_3", type: { value: "feed" }, screen_type: "C5678" },
  ];

  describe("getEntryById", () => {
    it("returns the entry matching the provided id", () => {
      expect(getEntryById(entries, { id: "entry_2" })).toEqual(entries[1]);
    });

    it("returns undefined if no entry matches the provided id", () => {
      expect(getEntryById(entries, { id: "unknown_id" })).toBeUndefined();
    });
  });

  describe("getEntryByPosition", () => {
    it("returns the entry matching the provided position", () => {
      expect(getEntryByPosition(entries, { position: 3 })).toEqual(entries[2]);
    });

    it("returns undefined if no entry matches the provided position", () => {
      expect(getEntryByPosition(entries, { position: 4 })).toBeUndefined();
    });
  });

  describe("getFirstEntry", () => {
    it("returns the first entry", () => {
      expect(getFirstEntry(entries, {})).toEqual(entries[0]);
    });
  });

  describe("getEntry", () => {
    it("returns the first entry if no param is provided", () => {
      expect(getEntry(entries, {})).toEqual(entries[0]);
    });

    it("returns the entry with the provided id", () => {
      expect(getEntry(entries, { id: "entry_2" })).toEqual(entries[1]);
    });

    it("returns the entry with the provided position", () => {
      expect(getEntry(entries, { position: 3 })).toEqual(entries[2]);
    });
  });
});

describe("formatEntry", () => {
  it("creates an object with the provided properties at the root and in the extensions", () => {
    const props = { param: "value" };

    expect(formatEntry(props)).toEqual(
      expect.objectContaining({
        ...props,
        extensions: props,
      })
    );
  });
});

describe("getHomeScreenId", () => {
  it("returns the home screen ID", () => {
    const rivers: Record<string, Partial<ZappRiver>> = {
      A1234: {
        id: "A1234",
        home: true,
      },
      B5678: {
        id: "B5678",
      },
    };

    expect(getHomeScreenId(rivers)).toEqual(rivers.A1234.id);
  });
});
