import { useEffect, useMemo } from 'react';
import dynamic from 'next/dynamic';

import type { ItemPageProps } from '~/src/components/ItemPage';
import type { PageTrackerContext } from '~/src/components/Page';
import type { FC } from 'react';

import { PageTypes } from '~/lib/types';
import ItemPage from '~/src/components/ItemPage';
import ItemPageHeader from '~/src/components/ItemPage/components/ItemPageHeader';
import ItemPageMetadata from '~/src/components/ItemPage/components/ItemPageMetadata';
import { toObservedLoadingComponent } from '~/src/components/ItemPage/components/LoadingObserver';
import {
  PageSectionElement,
  PageSections,
} from '~/src/components/ItemPage/components/SectionRenderer';
import { CORE_SECTION_COMPONENTS } from '~/src/components/ItemPage/constants';
import { PageSectionTypes } from '~/src/components/ItemPage/sections/types';
import LazyComponent from '~/src/components/LazyComponent';
import { useAppLoading } from '~/src/components/NextApp/lib/CoreUi';
import { PAGE_HEADER_HEIGHT } from '~/src/components/PageHeader';
import useHash from '~/src/hooks/useHash';
import useIsLargeScreen from '~/src/hooks/useIsLargeScreen';
import useSelectCustomPage from '~/src/hooks/useSelectCustomPage';
import { CustomPageActions } from './components/CustomPageActions';
import { CustomPageBanner } from './components/CustomPageBanner';
import { CustomPageToolbar } from './components/CustomPageToolbar';
import toStructuredData from './toStructuredData';
import useCustomPageContext from './useCustomPageContext';

const OrchardLegalFooterDynamic = dynamic(
  () => import('~/src/components/ItemPage/components/OrchardLegalFooter'),
  { ssr: true }
);

const VideosSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/VideosSection'),
  { loading: toObservedLoadingComponent() }
);

const MerchSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/MerchSection'),
  { loading: toObservedLoadingComponent() }
);

const ShowsSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/ShowsSection'),
  { loading: toObservedLoadingComponent() }
);

const StoriesSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/StoriesSection'),
  { loading: toObservedLoadingComponent() }
);

const VideoSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/VideoSection'),
  { loading: toObservedLoadingComponent() }
);

const FormSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/FormSection'),
  { loading: toObservedLoadingComponent() }
);

const PageHeaderSectionDynamic = dynamic(
  () => import('~/src/components/ItemPage/sections/PageHeaderSection'),
  { loading: toObservedLoadingComponent() }
);

const SECTION_COMPONENTS = {
  ...CORE_SECTION_COMPONENTS,

  [PageSectionTypes.VIDEOS]: VideosSectionDynamic,
  [PageSectionTypes.MERCH]: MerchSectionDynamic,
  [PageSectionTypes.SHOWS]: ShowsSectionDynamic,
  [PageSectionTypes.STORIES]: StoriesSectionDynamic,
  [PageSectionTypes.EXCLUSIVE_VIDEO]: VideoSectionDynamic,
  [PageSectionTypes.FORM]: FormSectionDynamic,
  [PageSectionTypes.PAGE_HEADER]: PageHeaderSectionDynamic,
};

export interface CustomPageProps
  extends Pick<ItemPageProps, 'withRedirectIfNeeded'> {
  customPageId: number;
}

const CustomPage: FC<CustomPageProps> = ({
  customPageId,
  withRedirectIfNeeded,
}) => {
  const isLargeScreen = useIsLargeScreen();
  const customPage = useSelectCustomPage(customPageId)!;
  const itemContext = useCustomPageContext({ customPage });
  const setIsAppLoading = useAppLoading();
  const { hasHashParam, backToBeforeFirstHash } = useHash();
  const editDetailsDialogOpen = hasHashParam('editDetails');

  useEffect(() => {
    setIsAppLoading(customPage.isLoading);
  }, [customPage.isLoading, setIsAppLoading]);

  return (
    <ItemPage
      key={customPageId}
      pageType={PageTypes.CUSTOM}
      hasContent={Boolean(customPage.name)} // TODO: Add useful check
      testId="customPage"
      error={customPage.error}
      itemContext={itemContext}
      isLoading={!!customPage.isLoading}
      isOwned={customPage.isOwned}
      isDraft={customPage.isDraft}
      pageBrand={customPage.pageBrand}
      pageOwnedByAccountIds={customPage.ownedByAccountIds}
      trackerContext={useMemo(
        (): PageTrackerContext => ({
          artistId: customPage.artistId,
          artistName: customPage.artistName,

          customPageId: customPage.id,
          customPageName: customPage.name,
        }),
        [customPage]
      )}
      withRedirectIfNeeded={withRedirectIfNeeded}
      pagePath={customPage.pagePath}
      header={useMemo(() => {
        const bannerHeight = isLargeScreen ? '5rem' : '4.5rem';
        const toolbarHeight = isLargeScreen ? '5rem' : '4.5rem';

        const banner = (
          <CustomPageBanner
            customPage={customPage}
            itemContext={itemContext}
            height={bannerHeight}
          />
        );

        const toolbar = (
          <CustomPageToolbar customPage={customPage} height={toolbarHeight} />
        );

        return {
          height: `calc(${PAGE_HEADER_HEIGHT} + ${toolbarHeight} + ${bannerHeight})`,

          content: (
            <>
              {banner}
              {toolbar}
              <ItemPageHeader
                pagePath={customPage.pagePath}
                userCanEdit={customPage.userCanEdit}
                renderActions={({ isOpen, actionButtonRef, onClose }) => {
                  return (
                    <CustomPageActions
                      itemContext={itemContext}
                      isOpen={isOpen}
                      actionButtonRef={actionButtonRef}
                      onClose={onClose}
                    />
                  );
                }}
              />
            </>
          ),
        };
      }, [customPage, isLargeScreen, itemContext])}
      content={useMemo(() => {
        return (
          <>
            <PageSections
              items={itemContext.layout.main}
              id=""
              components={SECTION_COMPONENTS}
              itemContext={itemContext}
              withTopMargin={false}
              groupSections={[
                [PageSectionTypes.PAGE_TITLE, PageSectionTypes.ICON_LINKS],
              ]}
            />
            <PageSectionElement>
              <OrchardLegalFooterDynamic />
            </PageSectionElement>
          </>
        );
      }, [itemContext])}
    >
      <ItemPageMetadata
        error={customPage.error}
        pagePath={customPage.pagePath}
        itemContext={itemContext}
        isOwned={customPage.isOwned}
        defaultTitle={customPage.name}
        defaultDescription={customPage.name}
        // REVIEW: this could be a <StructuredData> component instead
        // of having to pass props down the tree to <PageMetaData>
        // which is getting quite overloaded now
        toStructuredData={(params) =>
          // @ts-ignore
          toStructuredData({
            ...params,
            customPageName: customPage.name,
            artistName: customPage.artistName,
            artistPagePath: customPage.artistPagePath,
          })
        }
      />
      {editDetailsDialogOpen && (
        <LazyComponent
          // NOTE: webpack chunk name used to target script request in cypress
          loader={() =>
            import(
              /* webpackChunkName: "EditDetailsDialog" */ './components/EditDetailsDialog'
            )
          }
          page={customPage}
          onClose={backToBeforeFirstHash}
        />
      )}
    </ItemPage>
  );
};

export default CustomPage;
