import { useCallback, useEffect, useMemo } from 'react';
import Debug from 'debug';

import type { PageTrackerContext } from '~/src/components/Page';
import type { SelectedArtist, StoredArtist } from '~/src/store/artists/types';
import type { State } from '~/src/store/types';
import type { FC } from 'react';

import { PageTypes } from '~/lib/types';
import ItemPageEdit from '~/src/components/ItemPage/ItemPageEdit';
import ItemPageEditHeader from '~/src/components/ItemPage/ItemPageEdit/components/ItemPageEditHeader';
import { CORE_EDIT_SECTIONS } from '~/src/components/ItemPage/ItemPageEdit/constants';
import useOnSave from '~/src/components/ItemPage/ItemPageEdit/useOnSave';
import { toDescriptionFeatureItem } from '~/src/components/ItemPage/sections/BlockText/features';
import { toArtistSocialLinksFeatureItem } from '~/src/components/ItemPage/sections/IconLinksSection/features';
import {
  toBuyLinksFeatureItem,
  toStreamLinksFeatureItem,
} from '~/src/components/ItemPage/sections/ItemLinks/features';
import { toMerchFeatureItem } from '~/src/components/ItemPage/sections/MerchSection/features';
import MerchSectionEdit from '~/src/components/ItemPage/sections/MerchSection/MerchSectionEdit';
import { toPageTitleFeatureItem } from '~/src/components/ItemPage/sections/PageTitleSection';
import { toReleasesFeatureItem } from '~/src/components/ItemPage/sections/ReleasesSection/features';
import { toShowsFeatureItem } from '~/src/components/ItemPage/sections/ShowsSection/features';
import ShowsSectionEdit from '~/src/components/ItemPage/sections/ShowsSection/ShowsSectionEdit';
import { PageSectionTypes } from '~/src/components/ItemPage/sections/types';
import { toVideosFeatureItem } from '~/src/components/ItemPage/sections/VideosSection/features';
import { PresetTypes } from '~/src/components/ItemPage/types';
import { PAGE_HEADER_HEIGHT } from '~/src/components/PageHeader';
import useSelectArtist from '~/src/hooks/useSelectArtist';
import { useI18n } from '~/src/lib/i18n';
import { patchArtistConfig } from '~/src/store/artists/actions/config';
import { stageArtistForEditAction } from '~/src/store/artists/actions/edit';
import { createSelectArtist } from '~/src/store/artists/selectors';
import { selectStagedItemState } from '~/src/store/editStage/selectors';
import { useDispatch, useSelector } from '~/src/store/redux';
import useArtistItemContext from '../lib/useArtistItemContext';

const debug = Debug('songwhip/ItemPageArtistEdit');

const PAGE_SECTIONS_COMPONENTS = {
  [PageSectionTypes.MERCH]: MerchSectionEdit,
  [PageSectionTypes.SHOWS]: ShowsSectionEdit,
};

const sectionComponents = {
  ...CORE_EDIT_SECTIONS,
  ...PAGE_SECTIONS_COMPONENTS,
};

const EditArtistPage: FC<{
  artistId: number;
  stagedArtist: SelectedArtist;
  originalArtist: SelectedArtist;
}> = ({ artistId, stagedArtist, originalArtist }) => {
  const i18n = useI18n();
  const dispatch = useDispatch();

  const originalItemContext = useArtistItemContext({
    artist: originalArtist,
    withAllLinks: true,
  });

  const itemContext = useArtistItemContext({
    artist: stagedArtist,
    withAllLinks: true,
    originalItemContext,
  });

  const { save } = useOnSave({
    itemContext,
    pagePath: stagedArtist.pagePath,

    onSave: async (config) => {
      debug('on save', config);

      await dispatch(
        patchArtistConfig({
          artistId,
          config,
          lastUpdatedAt: stagedArtist.updatedAtTimestamp,

          showToastOnError: (error) => {
            if (error.code === 'ITEM_WRITE_CONFLICT') {
              return false;
            }

            return true;
          },
        })
      );
    },
  });

  return (
    <ItemPageEdit
      key={artistId}
      pageType={PageTypes.EDIT}
      itemContext={itemContext}
      hasContent={!!stagedArtist.links}
      testId="editArtistPage"
      error={stagedArtist?.error}
      isLoading={false}
      userCanEdit={!!stagedArtist?.userCanEdit}
      pagePath={stagedArtist.pagePath}
      header={useMemo(() => {
        return {
          content: (
            <ItemPageEditHeader
              pagePath={stagedArtist.pagePath}
              saveChanges={save}
              // renderContent={() => {
              //   return 'header content';
              // }}
            />
          ),
          height: PAGE_HEADER_HEIGHT,
        };
      }, [save])}
      sectionComponents={sectionComponents}
      getAddSectionItems={useCallback(
        ({ baseItems }) => [
          // page specific sections
          toStreamLinksFeatureItem({ i18n, itemContext }),
          toBuyLinksFeatureItem({ i18n, itemContext }),
          toArtistSocialLinksFeatureItem({ i18n, itemContext }),

          // main sections
          toPageTitleFeatureItem({ i18n, itemContext }),
          toDescriptionFeatureItem({
            i18n,
            preset: PresetTypes.DESCRIPTION,
            itemContext,
          }),

          // other sections
          toVideosFeatureItem({ i18n, itemContext }),
          toMerchFeatureItem({ i18n, itemContext }),
          toShowsFeatureItem({ i18n, itemContext }),
          toReleasesFeatureItem({ i18n, itemContext }),

          ...baseItems,
        ],
        [i18n, itemContext]
      )}
      trackerContext={useMemo(
        (): PageTrackerContext => ({
          artistId: stagedArtist.id,
          artistName: stagedArtist.name,
        }),
        [stagedArtist]
      )}
    />
  );
};

const useStagedArtist = (artistId: number) => {
  const selectStagedArtist = useMemo(() => {
    return createSelectArtist((state) =>
      selectStagedItemState<StoredArtist>(state)
    );
  }, []);

  return useSelector((state: State) => selectStagedArtist(state, artistId));
};

const EditArtistPageContainer = ({ artistId }: { artistId: number }) => {
  const dispatch = useDispatch();
  const stagedArtist = useStagedArtist(artistId);
  const originalArtist = useSelectArtist(artistId);

  useEffect(() => {
    dispatch(stageArtistForEditAction(artistId));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [artistId]);

  // TODO: Show an error message or redirect back to the artist page
  if (!originalArtist) return null;

  // TODO: The staged artist would only be null on the first render,
  // but we should handle this case in the future
  if (!stagedArtist) return null;

  return (
    <EditArtistPage
      artistId={artistId}
      stagedArtist={stagedArtist}
      originalArtist={originalArtist}
    />
  );
};

export default EditArtistPageContainer;
