import { 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 {
  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 { PAGE_HEADER_HEIGHT } from '~/src/components/PageHeader';
import useHash from '~/src/hooks/useHash';
import useIsLargeScreen from '~/src/hooks/useIsLargeScreen';
import useSelectAlbum from '~/src/hooks/useSelectAlbum';
import useSelectArtists from '~/src/hooks/useSelectArtists';
import { useI18n } from '~/src/lib/i18n';
import {
  AlbumBanner,
  shouldShowMissingServicesBanner,
} from './components/AlbumBanner';
import { AlbumPageActions } from './components/AlbumPageActions';
import { ALBUM_PAGE_SECTION_COMPONENTS } from './constants';
import toStructuredData from './hooks/toStructuredData';
import useAlbumChecks from './hooks/useAlbumChecks';
import useAlbumItemContext from './hooks/useAlbumItemContext';

const sectionComponents = {
  ...CORE_SECTION_COMPONENTS,
  ...ALBUM_PAGE_SECTION_COMPONENTS,
};

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

export interface ItemPageAlbumProps
  extends Pick<ItemPageProps, 'withRedirectIfNeeded'> {
  albumId: number;
  withAlbumChecks?: boolean;
}

const AlbumPage: FC<ItemPageAlbumProps> = ({
  albumId,
  withAlbumChecks = true,
  withRedirectIfNeeded = true,
  ...itemPageProps
}) => {
  const { t } = useI18n();

  const album = useSelectAlbum(albumId)!;
  const itemContext = useAlbumItemContext({ album });
  const isLargeScreen = useIsLargeScreen();

  const { showArtistIds } = itemContext.config;
  const artists = useSelectArtists(showArtistIds);
  const artistNames = artists?.map(({ name }) => name).join(', ');
  const { hasHashParam, getHashParam, backToBeforeFirstHash } = useHash();
  const editDetailsHashValue = getHashParam('editDetails');
  const editDetailsDialogOpen = hasHashParam('editDetails');
  const isFromBanner = editDetailsHashValue === 'from-banner';
  const showMissingServicesBanner = shouldShowMissingServicesBanner(album);

  if (withAlbumChecks) {
    // TODO: this should fixed
    /* eslint-disable-next-line react-hooks/rules-of-hooks */
    useAlbumChecks(album);
  }

  return (
    <ItemPage
      testId="albumPage"
      pageType={PageTypes.ALBUM}
      key={albumId}
      isOwned={album.isOwned}
      isDraft={album.isDraft}
      pageBrand={album.pageBrand}
      pagePath={album.pagePath}
      itemContext={itemContext}
      pageOwnedByAccountIds={album.ownedByAccountIds}
      isLoading={!!album.isLoading}
      hasContent={!!album.name && !album.isShallow}
      withRedirectIfNeeded={withRedirectIfNeeded}
      error={album.error}
      trackerContext={useMemo(
        (): PageTrackerContext => ({
          albumId: album.id,
          albumName: album.name,
          artistId: album.artistId,
          artistName: album.artistName,
        }),
        [album]
      )}
      header={useMemo(() => {
        const bannerHeight = isLargeScreen ? '5rem' : '4.5rem';
        const banner = <AlbumBanner album={album} height={bannerHeight} />;

        return {
          height: `calc(${PAGE_HEADER_HEIGHT} + ${
            Boolean(banner) ? bannerHeight : '0rem'
          })`,

          content: (
            <>
              {banner}
              <ItemPageHeader
                pagePath={album.pagePath}
                userCanEdit={album.userCanEdit}
                renderActions={({ isOpen, actionButtonRef, onClose }) => {
                  return (
                    <AlbumPageActions
                      itemContext={itemContext}
                      isOpen={isOpen}
                      actionButtonRef={actionButtonRef}
                      onClose={onClose}
                      showMissingServicesBanner={showMissingServicesBanner}
                      userCanEdit={!!album.userCanEdit}
                    />
                  );
                }}
              />
            </>
          ),
        };
      }, [album, isLargeScreen, showMissingServicesBanner, itemContext])}
      content={useMemo(() => {
        return (
          <>
            <PageSections
              items={itemContext.layout.main}
              id=""
              components={sectionComponents}
              itemContext={itemContext}
              withTopMargin={false}
              groupSections={[
                [PageSectionTypes.PAGE_TITLE, PageSectionTypes.ICON_LINKS],
              ]}
            />
            <PageSectionElement>
              <OrchardLegalFooterDynamic />
            </PageSectionElement>
          </>
        );
      }, [album])}
      {...itemPageProps}
    >
      <ItemPageMetadata
        error={album.error}
        pagePath={album.pagePath}
        isOwned={album.isOwned}
        itemContext={itemContext}
        defaultTitle={
          album.name &&
          t('item.albumPageMetaTitle', {
            albumName: album.name,
            artistNames: artistNames ?? '?',
          })
        }
        defaultDescription={
          album.name &&
          t('item.albumPageMetaDescription', {
            albumName: album.name,
            artistNames: artistNames ?? '?',
          })
        }
        // 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: any) => {
          return toStructuredData({
            ...params,
            albumName: album.name,
            artistName: album.artistName,
            artistPagePath: album.artistPagePath,
            // TODO: add artist image (need resolving to full url)
            artistImageUrl: undefined,
          });
        }}
      />
      {editDetailsDialogOpen && (
        <LazyComponent
          // NOTE: webpack chunk name used to target script request in cypress
          loader={() =>
            import(
              /* webpackChunkName: "EditDetailsDialog" */ './components/EditDetailsDialog'
            )
          }
          onClose={backToBeforeFirstHash}
          album={album}
          isFromBanner={isFromBanner}
        />
      )}
    </ItemPage>
  );
};

export default AlbumPage;
