import { describe, it, expect } from '#test';
import { elevate, esales, queries, notifications } from './mod.ts';
import { Query } from './query.ts';
import { Notification } from './notification.ts';
import * as lib from './mod.ts';


const suite = describe('lib');
const session = () => ({ customerKey: '', sessionKey: '' });

it(suite, 'should export legacy entrypoint for backwards compat', () => {
  expect(elevate).toBe(esales);
});

it(suite, 'should not export any internal values publicly', () => {
  const internalKeys = Object.keys(lib).filter(k => /^_/.test(k));
  expect(internalKeys.length).toBe(0);
});

it(suite, 'should throw if config is invalid', () => {
  // deno-lint-ignore no-explicit-any
  expect(() => elevate(undefined as any)).toThrow();
});

it(suite, 'should have correct properties after instantiation', () => {
  const api = elevate({ clusterId: 'w000000', market: 'a', locale: 'a', touchpoint: 'desktop', session });

  api satisfies { clusterUrl: string, query: Query, notify: Notification };
  expect(typeof api.clusterUrl).toBe('string');
  expect(api.query).toBeInstanceOf(Query);
  expect(api.notify).toBeInstanceOf(Notification);
});

it(suite, 'should be able to create Query object only for tree-shaking purposes', () => {
  const query = queries({ clusterId: 'w000000', market: 'a', locale: 'a', touchpoint: 'desktop', session });

  query satisfies Query;
  expect(query).toBeInstanceOf(Query);
});

it(suite, 'should be able to create Notification object only for tree-shaking purposes', () => {
  const notify = notifications({ clusterId: 'w000000', market: 'a', session });

  notify satisfies Notification;
  expect(notify).toBeInstanceOf(Notification);
});

it(suite, 'should pass Config.clusterUrl onwards to API instance', () => {
  const base = { market: 'a', locale: 'a', touchpoint: 'desktop', session } as const;

  expect(elevate({ ...base, clusterId: 'https://acme.com/' }).clusterUrl).toBe('https://acme.com/');
  expect(elevate({ ...base, clusterId: 'w1337ed' }).clusterUrl).toBe('https://w1337ed.api.esales.apptus.cloud/');
});

it(suite, 'should export all public types', () => {
  // GENERAL
  type Entrypoint =
    lib.Config | lib.NotificationConfig | lib.Session | lib.SessionMetadata | lib.Touchpoint | lib.LocalStorageSession;
  type CommonModels =
    lib.Algorithm | lib.AutoCorrect | lib.Availability | lib.Badge | lib.BadgeType | lib.Breadcrumb |
    lib.CheckboxFacet | lib.ColorFacet | lib.ColorFacetValue | lib.ContentItem | lib.ContentList |
    lib.ContentListPage | lib.ContentSortType | lib.CustomAttribute | lib.CustomAttributes | lib.DidYouMean |
    lib.Facet | lib.FacetParams | lib.FacetRange | lib.FacetType | lib.FacetTextSort | lib.FacetValue |
    lib.Image | lib.ImageEffect | lib.ImageSource | lib.MeasurementResult | lib.Navigation | lib.NavigationItemType |
    lib.NavigationLabelNode | lib.NavigationLabelStateNode | lib.NavigationLinkNode | lib.NavigationLinkStateNode |
    lib.NavigationNode | lib.NavigationProductNode | lib.NavigationProductStateNode | lib.NavigationSpacerNode |
    lib.NavigationSpacerStateNode | lib.NavigationStateNode | lib.Price | lib.PriceResult | lib.PrimaryList |
    lib.ProductGroup | lib.Product | lib.RangeFacet | lib.RecommendationList | lib.RecommendationListPage |
    lib.SecondaryList | lib.SizeFacet | lib.SizeFormat | lib.SizeType | lib.Sort | lib.SortOption | lib.SortType |
    lib.SwatchType | lib.TextFacet | lib.TextFacetValue | lib.Timestamp | lib.TypedCustomAttributes |
    lib.TypedCustomMeasurementAttribute | lib.TypedCustomNumberAttribute | lib.TypedCustomAttribute |
    lib.Variant | lib.Visualization;

  // ENDPOINTS
  // AddToCartPopup
  type AllAddToCartPopup = lib.AddToCartPopup | lib.AddToCartPopupParams | lib.AddToCartPopupBody;

  // Autocomplete
  type AllAutocomplete =
    lib.Autocomplete | lib.AutocompleteParams | lib.AutocompleteBody | lib.PhraseSuggestion |
    lib.ContentSuggestion | lib.RecentSearch;

  // CartPage
  type AllCartPage = lib.CartPage | lib.CartPageParams | lib.CartPageBody;

  // ContentInformation
  type AllContentInformation = lib.ContentInformation | lib.ContentInformationParams;

  // ContentSearchPage
  type AllContentSearchPage =
    lib.ContentSearchPage | lib.ContentSearchPageParams | lib.ContentSearchPageBody |
    lib.ContentSearchOrigin | lib.PrimaryContentList;

  // LandingPage
  type AllLandingPage = lib.LandingPage | lib.LandingPageParams | lib.LandingPageBody | lib.SearchEngineOptimization;

  // NavigationTree
  type AllNavigationTree = lib.NavigationTree | lib.NavigationTreeParams;

  // ProductPage
  type AllProductPage = lib.ProductPage | lib.ProductPageParams | lib.ProductPageBody;

  // SearchPage
  type AllSearchPage = lib.SearchPage | lib.SearchPageParams | lib.SearchPageBody | lib.SearchOrigin;

  ({}) satisfies Record<
    string,
    Entrypoint | CommonModels | AllAddToCartPopup | AllAutocomplete | AllCartPage | AllContentInformation |
    AllContentSearchPage | AllLandingPage | AllNavigationTree | AllProductPage | AllSearchPage
  >;
});
