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

import type { PageTrackerContext } from '~/src/components/Page';
import type {
  SelectedCustomPage,
  StoredCustomPage,
} from '~/src/store/customPages/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 { FormSectionEdit } from '~/src/components/ItemPage/sections/FormSection/FormSectionEdit';
import { toMerchFeatureItem } from '~/src/components/ItemPage/sections/MerchSection/features';
import { toPageHeaderFeatureItem } from '~/src/components/ItemPage/sections/PageHeaderSection';
import { PageHeaderSectionEdit } from '~/src/components/ItemPage/sections/PageHeaderSection/PageHeaderSectionEdit';
import { toPageTitleFeatureItem } from '~/src/components/ItemPage/sections/PageTitleSection';
import { toShowsFeatureItem } from '~/src/components/ItemPage/sections/ShowsSection/features';
import { toStoriesFeatureItem } from '~/src/components/ItemPage/sections/StoriesSection/features';
import StoriesSectionEdit from '~/src/components/ItemPage/sections/StoriesSection/StoriesSectionEdit';
import { PageSectionTypes } from '~/src/components/ItemPage/sections/types';
import { toVideoFeatureItem } from '~/src/components/ItemPage/sections/VideoSection/features';
import VideoSectionEdit from '~/src/components/ItemPage/sections/VideoSection/VideoSectionEdit';
import { PAGE_HEADER_HEIGHT } from '~/src/components/PageHeader';
import useIsEnabled from '~/src/hooks/useIsEnabled';
import useSelectCustomPage from '~/src/hooks/useSelectCustomPage';
import { useI18n } from '~/src/lib/i18n';
import { patchCustomPageConfig } from '~/src/store/customPages/actions/config';
import { stageCustomPageForEditAction } from '~/src/store/customPages/actions/edit';
import { createSelectCustomPage } from '~/src/store/customPages/selectors';
import { selectStagedItemState } from '~/src/store/editStage/selectors';
import { useDispatch, useSelector } from '~/src/store/redux';
import { Features } from '~/src/store/session/types';
import useCustomPageContext from './useCustomPageContext';

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

interface Props {
  customPageId: number;
}

const SECTION_COMPONENTS = {
  ...CORE_EDIT_SECTIONS,
  [PageSectionTypes.STORIES]: StoriesSectionEdit,
  [PageSectionTypes.EXCLUSIVE_VIDEO]: VideoSectionEdit,
  [PageSectionTypes.FORM]: FormSectionEdit,
  [PageSectionTypes.PAGE_HEADER]: PageHeaderSectionEdit,
};

const CustomPageEdit: FC<
  Props & {
    stagedCustomPage: SelectedCustomPage;
    customPage: SelectedCustomPage;
  }
> = ({ customPageId, stagedCustomPage, customPage }) => {
  const i18n = useI18n();
  const originalItemContext = useCustomPageContext({ customPage });
  const dispatch = useDispatch();

  const isExclusiveVideoEnabled = useIsEnabled(Features.EXCLUSIVE_VIDEO);

  const itemContext = useCustomPageContext({
    customPage: stagedCustomPage,
    originalItemContext,
  });

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

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

      await dispatch(
        patchCustomPageConfig({
          customPageId,
          config,
          lastUpdatedAt: customPage.updatedAtTimestamp,

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

            return true;
          },
        })
      );

      // When the page is a draft override the toast success text to use
      // 'saved' instead of 'published'. Using "published" might cause panic
      // if the page is sensitive and the owner believes it's private.
      if (customPage.isDraft) {
        return i18n.t('item.events.changesSaved');
      }
    },
  });

  return (
    <ItemPageEdit
      key={customPageId}
      pageType={PageTypes.EDIT}
      itemContext={itemContext}
      hasContent={Boolean(customPage.name)}
      testId="customPageEdit"
      error={customPage.error}
      isLoading={!!customPage.isLoading}
      pagePath={customPage.pagePath}
      userCanEdit={!!customPage.userCanEdit}
      sectionComponents={SECTION_COMPONENTS}
      header={useMemo(() => {
        return {
          height: PAGE_HEADER_HEIGHT,
          content: (
            <ItemPageEditHeader
              pagePath={stagedCustomPage.pagePath}
              saveChanges={save}
            />
          ),
        };
      }, [stagedCustomPage])}
      getAddSectionItems={useCallback(
        ({ baseItems, itemContext }) => {
          return [
            // page specific sections
            toStoriesFeatureItem({ i18n, itemContext }),
            isExclusiveVideoEnabled &&
              toVideoFeatureItem({ i18n, itemContext }),

            // main sections
            toPageTitleFeatureItem({ i18n, itemContext }),
            toPageHeaderFeatureItem({ i18n, itemContext }),

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

            ...baseItems,
          ];
        },
        [i18n]
      )}
      trackerContext={useMemo(
        (): PageTrackerContext => ({
          artistId: customPage.artistId,
          artistName: customPage.artistName,

          customPageId: customPage.id,
          customPageName: customPage.name,
        }),
        [customPage]
      )}
    />
  );
};

const useStagedCustomPage = (customPageId: number) => {
  const selectStagedCustomPage = useMemo(() => {
    return createSelectCustomPage({
      selectStateItem: (state) =>
        selectStagedItemState<StoredCustomPage>(state),
    });
  }, []);

  return useSelector((state: State) =>
    selectStagedCustomPage(state, customPageId)
  );
};

const CustomPageEditContainer = ({ customPageId }: Props) => {
  const dispatch = useDispatch();
  const stagedCustomPage = useStagedCustomPage(customPageId);
  const customPage = useSelectCustomPage(customPageId);

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

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

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

  return (
    <CustomPageEdit
      customPageId={customPageId}
      stagedCustomPage={stagedCustomPage}
      customPage={customPage}
    />
  );
};

export default CustomPageEditContainer;
