import { lazy } from 'react';
import { getSectionExtraField } from 'gatsby-core-theme/src/helpers/getters';
import Content from 'gatsby-core-theme/src/components/molecules/content';
import Toplist from 'gatsby-core-theme/src/components/organisms/toplist';
import Anchor from 'gatsby-core-theme/src/components/organisms/anchor/template-one';
import getSpotlightComponent from '~molecules/spotlights_v2';
import Cards from '../../../../components/organisms/cards';
import InfoGrid from '../../../../components/atoms/info-grid/template-one';
import CountrySelector from '../../../../components/atoms/country-selector';
import {
  HIDE_MODULE_HEADER_MODULES,
  LOTTO_MODULES,
  NO_SUSPENSE_MODULES,
  SPORTSTAKE_FIXTURE_MODULES,
  SPORTSTAKE_MODULES,
  SPORTSTAKE_RESULT_MODULES,
} from './module-constants';
import {
  getLottoProps,
  getSportstakeFixtureProps,
  getSportstakeResultProps,
} from './module-props';

const sportstakeFixtureEntries = Object.fromEntries(
  SPORTSTAKE_FIXTURE_MODULES.map((name) => [
    name,
    {
      load: () => import('../../../../components/molecules/sportstake/fixtures'),
      shouldRender: (_, ctx) => Boolean(ctx.serverData?.fixtures?.data?.length),
      getProps: getSportstakeFixtureProps,
      sportstakeSuspense: true,
    },
  ])
);

const sportstakeResultEntries = Object.fromEntries(
  SPORTSTAKE_RESULT_MODULES.map((name) => [
    name,
    {
      load: () => import('../../../../components/molecules/sportstake/results'),
      shouldRender: (_, ctx) => Boolean(ctx.serverData?.results?.data?.length),
      getProps: getSportstakeResultProps,
      sportstakeSuspense: true,
    },
  ])
);

const lottoEntries = Object.fromEntries(
  LOTTO_MODULES.map((name) => [
    name,
    {
      load: () => import('../../../../components/molecules/sportstake/lotto-module'),
      shouldRender: (_, ctx) =>
        Boolean(ctx.serverData?.lotto?.data?.find((x) => x?.name === ctx.module?.name)),
      getProps: getLottoProps,
      sportstakeSuspense: true,
    },
  ])
);

const iframeResolver = (ctx) => {
  if (ctx.module?.value_type === 'template_block') {
    return lazy(() => import('../../../../components/molecules/game-iframe'));
  }
  return lazy(() => import('gatsby-core-theme/src/components/atoms/iframe'));
};

export const MODULE_REGISTRY = {
  content: { component: Content, suspense: false },
  top_list: { component: Toplist, suspense: false },
  archive: {
    load: () => import('gatsby-core-theme/src/components/organisms/archive'),
    shouldRender: (module) => Boolean(module?.items?.length),
  },
  counter: {
    load: () => import('gatsby-core-theme/src/components/molecules/counter'),
  },
  comments: {
    load: () => import('gatsby-core-theme/src/components/organisms/comments'),
  },
  contact_form: {
    load: () => import('gatsby-core-theme/src/components/atoms/contact-form'),
  },
  cards: { component: Cards },
  cards_v2: { component: Cards, suspense: false, hideModuleHeader: true },
  pros_and_cons: {
    load: () => import('gatsby-core-theme/src/components/molecules/pros-cons'),
  },
  accordion: {
    load: () => import('gatsby-core-theme/src/components/organisms/accordion'),
  },
  anchor: {
    component: Anchor,
    suspense: false,
    shouldRender: (module) => Boolean(module?.items?.length),
  },
  carousel: {
    load: () => import('gatsby-core-theme/src/components/organisms/carousel'),
    shouldRender: (module) =>
      Boolean(
        module?.items?.length &&
          module.items.filter((item) => item.image === null).length === 0
      ),
  },
  bonus: {
    load: () => import('gatsby-core-theme/src/components/molecules/bonus/template-one'),
    getProps: ({ module, page }) => ({
      operator: module?.value,
      logo: module?.value?.logo_url,
      hasLink: true,
      pageTemplate: page?.template,
      isStickyCta: false,
    }),
  },
  image: {
    load: () => import('gatsby-core-theme/src/components/atoms/image'),
  },
  spotlights: {
    resolveComponent: (ctx) => getSpotlightComponent(ctx.module),
  },
  faq: {
    load: () => import('../../../../components/molecules/faq'),
    shouldRender: (module) => module?.display_front_end === '1',
  },
  country_selector: { component: CountrySelector, suspense: false },
  horse_racing_calculator: {
    load: () => import('../../../../components/molecules/horse-calculator'),
  },
  review_summary: {
    load: () => import('../../../../components/molecules/operator-summary'),
  },
  review_disclaimer: {
    load: () => import('../../../../components/atoms/disclaimer/review-disclaimer'),
  },
  game_iframe: { resolveComponent: iframeResolver },
  iframe: {
    resolveComponent: iframeResolver,
    getProps: ({ module }) => ({ src: module?.iframe_source }),
  },
  info_grid: {
    component: InfoGrid,
    suspense: false,
    shouldRender: (_, ctx) =>
      getSectionExtraField(null, ctx.page, 'operator_is_placeholder') !== '1',
    getProps: ({ page }) => ({
      templateThree: page.type.includes('author'),
    }),
  },
  information_grid: {
    component: InfoGrid,
    suspense: false,
    shouldRender: (_, ctx) =>
      getSectionExtraField(null, ctx.page, 'operator_is_placeholder') !== '1',
    getProps: ({ page }) => ({
      templateThree: page.type.includes('author'),
    }),
  },
  operator_information_block: {
    component: InfoGrid,
    suspense: false,
    shouldRender: (_, ctx) =>
      getSectionExtraField(null, ctx.page, 'operator_is_placeholder') !== '1',
    getProps: ({ page }) => ({
      templateThree: page.type.includes('author'),
    }),
  },
  content_box: {
    load: () => import('gatsby-core-theme/src/components/atoms/content-box'),
  },
  timeline: {
    load: () =>
      import('gatsby-core-theme/src/components/molecules/content-and-custom-module'),
  },
  welcome_bonus: {
    load: () => import('../../../../components/molecules/operator-welcome-bonus'),
  },
  widget: {
    load: () => import('../../../../components/molecules/widget'),
  },
  score_gauges: {
    load: () => import('../../../../components/molecules/game-score-gauge'),
  },
  site_contacts: {
    load: () => import('../../../../components/atoms/site-contacts'),
    shouldRender: (_, ctx) => ctx.page?.siteSchema?.email !== null,
  },
  newsletter_optin: {
    load: () => import('../../../../components/molecules/newsletter-optin'),
  },
  wagering_calculator: {
    load: () => import('../../../../components/molecules/wagering-calculator'),
  },
  social_icons: {
    load: () => import('../../../../components/atoms/social-icons'),
    getProps: ({ socialIcons }) =>
      Object.values(socialIcons || {}).some((value) => value) ? { socialIcons } : {},
  },
  newsletter: {
    load: () => import('gatsby-core-theme/src/components/molecules/newsletter'),
    getProps: () => ({ isSticky: false }),
  },
  multiple_contributors: {
    load: () => import('../../../../components/molecules/multiple-contributors'),
    shouldRender: (_, ctx) => Boolean(ctx.EEAT && ctx.page?.allAuthors && !ctx.isContactUsPage),
    getProps: ({ page }) => ({
      authors: page.allAuthors && page.allAuthors,
      reviewer: page.reviewer_id && page?.reviewer,
      page,
    }),
  },
  lotto_uk_49_template: {
    load: () => import('../../../../components/molecules/lotto-uk-49'),
    getProps: ({ serverData }) => ({ serverData: serverData?.lottouk49 }),
  },
  teatime_and_lunchtime_frame: {
    load: () => import('../../../../components/molecules/teatime-lunchtime-frame'),
  },
  teatime_and_lunchtime_disclaimer: {
    load: () => import('../../../../components/atoms/teatime-lunchtime-disclaimer'),
  },
  disquss: {
    load: () => import('~atoms/disquss'),
  },
  rating_casinos: {
    load: () => import('../../../../components/atoms/ratings-with-comments'),
  },
  google_preferred_source: {
    load: () => import('../../../../components/molecules/google-preferred-source'),
    hideModuleHeader: true,
  },
  ...sportstakeFixtureEntries,
  ...sportstakeResultEntries,
  ...lottoEntries,
};

export function resolveModule(name, ctx) {
  const config = MODULE_REGISTRY[name];
  if (!config) {
    return null;
  }

  if (config.shouldRender && !config.shouldRender(ctx.module, ctx)) {
    return null;
  }

  let Component = config.component;
  if (config.resolveComponent) {
    Component = config.resolveComponent(ctx);
  } else if (!Component && config.load) {
    Component = lazy(config.load);
  }

  if (!Component) {
    return null;
  }

  const props = config.getProps
    ? config.getProps(ctx)
    : { anchorLabel: ctx.anchorLabel };

  const hideModuleHeader =
    config.hideModuleHeader || HIDE_MODULE_HEADER_MODULES.has(name);
  const suspense = config.suspense === false ? false : !NO_SUSPENSE_MODULES.has(name);
  const sportstakeSuspense = config.sportstakeSuspense || SPORTSTAKE_MODULES.includes(name);

  return {
    Component,
    props,
    meta: { hideModuleHeader, suspense, sportstakeSuspense },
  };
}
