import { memo, useCallback } from 'react';
import Debug from 'debug';

import type { MappedPartialAlbum } from '~/lib/songwhipApi/mapper';
import type { ClickableOnClick } from '~/src/components/Clickable';
import type { FC, ReactNode } from 'react';
import type { PageSectionComponent } from '../../types';
import type { ReleasesSectionProps } from '../types';

import Box from '~/src/components/Box';
import Clickable from '~/src/components/Clickable';
import DialogBox from '~/src/components/DialogBox';
import { DialogBoxHeader } from '~/src/components/DialogBox/DialogBoxHeader';
import { useConfirmNavigation } from '~/src/components/ItemPage/ItemPageEdit/useConfirmNavigation';
import { useEditActions } from '~/src/components/ItemPage/ItemPageEdit/useEditActions';
import Link from '~/src/components/Link2';
import ListItem from '~/src/components/ListItem';
import {
  useAppAlert,
  useAppConfirm,
} from '~/src/components/NextApp/lib/CoreUi';
import { SortableItem } from '~/src/components/Sortable';
import Sticky from '~/src/components/Sticky';
import Text from '~/src/components/Text';
import useHash from '~/src/hooks/useHash';
import { useI18n } from '~/src/lib/i18n';
import { useAppRouter } from '~/src/lib/router2';
import darkTheme from '~/src/lib/theme/dark';
import { usePageTheme } from '../../../hooks/theme';
import { EditWrapper } from '../../lib/EditWrapper';
import HorizontalItem from '../../lib/HorizontalItemsSection/HorizontalItem';
import SectionTitle from '../../lib/SectionTitle';
import SortableHorizontalScroller from '../../lib/SortableHorizontalScroller';
import { MAX_ITEMS } from '../constants';
import { useResolveAlbums } from '../utils';
import ReleasesSectionSettings from './ReleasesSectionSettings';

const debug = Debug('songwhip/ReleasesSectionEdit');
const HASH_PARAM = 'releases';

const ReleasesSectionEdit: PageSectionComponent<ReleasesSectionProps> = ({
  title,
  albumIds,
  albums,
  sectionPath,
  pagePeeking,
}) => {
  return (
    <div data-testid="releasesEdit">
      <EditWrapper
        padding="1.6rem 1rem 2rem"
        sectionPath={sectionPath}
        renderSettingsContent={useCallback(
          ({ close }) => (
            <ReleasesSectionSettings
              title={title}
              pagePeeking={pagePeeking}
              sectionPath={sectionPath}
              onSubmit={close}
            />
          ),
          [title, pagePeeking]
        )}
      >
        <ReleasesSectionEditContent
          title={title}
          albumIds={albumIds}
          albums={albums}
          sectionPath={sectionPath}
        />
      </EditWrapper>
    </div>
  );
};

const ReleasesSectionEditContent = memo<
  {
    title: string;
    sectionPath: string;
  } & Pick<ReleasesSectionProps, 'albumIds' | 'albums'>
>(({ albums, albumIds = albums
    ?.map(({ id }) => id)
    .slice(0, MAX_ITEMS) ?? [], title, sectionPath }) => {
  const { updateLayoutSection } = useEditActions();
  const items = useResolveAlbums({ albumIds, albums });
  const hasMoreThan2 = !!albums && albums.length > 3;
  const appConfirm = useAppConfirm();
  const pageTheme = usePageTheme();

  const onItemClick = useCallback<ClickableOnClick<number>>(
    async ({ data: albumId }) => {
      const confirmed = await appConfirm({
        content: 'Remove this release?',
      });

      if (confirmed) {
        updateLayoutSection<ReleasesSectionProps>({
          sectionPath,

          changedProps: {
            albumIds: albumIds.filter((id) => id !== albumId),
          },
        });
      }
    },
    [albumIds]
  );

  return (
    <>
      <SectionTitle text={title} minHeight="3.5rem" isSticky={false} />
      <SortableHorizontalScroller
        margin="0.5rem -.8rem 0"
        centerContent
        arrowOffsetY={30}
        gradientColor={pageTheme.backgroundColor}
        contentStyle={{
          padding: '0 1rem',
        }}
        renderContent={useCallback(
          ({ itemStyle, itemClassName }) => {
            return (
              items?.map(({ id, name, image }) => {
                return (
                  <SortableItem
                    key={id}
                    className={`releaseSectionItem ${itemClassName}`}
                    style={{
                      ...itemStyle,
                      padding: '0 0.5rem',
                      width: hasMoreThan2 ? '14rem' : '33%',
                    }}
                  >
                    <li>
                      <HorizontalItem
                        data={id}
                        text={name}
                        title={name}
                        image={image}
                        textLineClamp={1}
                        imageStyle={{
                          background: pageTheme.backgroundColor,
                          border: `solid 1px ${pageTheme.backgroundColor}`,
                        }}
                        onClick={onItemClick as any}
                        withHoverOpacityFrom={0.9}
                      />
                    </li>
                  </SortableItem>
                );
              }) || null
            );
          },
          [items, pageTheme]
        )}
        onDrop={useCallback(
          ({ removedIndex, addedIndex }) => {
            const albumIdsNext = [...albumIds];
            const [removed] = albumIdsNext.splice(removedIndex, 1);

            albumIdsNext.splice(addedIndex, 0, removed);
            debug('order change', albumIdsNext);

            updateLayoutSection<ReleasesSectionProps>({
              sectionPath,

              changedProps: {
                albumIds: albumIdsNext,
              },
            });
          },
          [albums, updateLayoutSection]
        )}
      />
      <AddReleaseButton
        sectionPath={sectionPath}
        albumIds={albumIds}
        albums={albums}
        onSubmit={(albumId) => {
          updateLayoutSection<ReleasesSectionProps>({
            sectionPath,

            changedProps: {
              albumIds: [albumId, ...albumIds],
            },
          });
        }}
      />
      {/* override clickable hover style when dragging */}
      <style jsx global>{`
        .smooth-dnd-ghost.horizontalSortableItem .image {
          box-shadow: 0 0 4rem black;
        }
      `}</style>
    </>
  );
});

const toAddDialogHashParam = (sectionPath: string) =>
  `${HASH_PARAM}:${sectionPath}:add`;

const AddReleaseButton: FC<{
  sectionPath: string;
  albumIds: number[];
  albums: MappedPartialAlbum[] | undefined;
  onSubmit: (albumId: number) => void;
}> = ({ sectionPath, onSubmit, albumIds, albums }) => {
  const { t, tx } = useI18n();

  const { backToBeforeFirstHash, setHashParam, hashParams } = useHash();
  const hashParam = toAddDialogHashParam(sectionPath);
  const maxItemsReached = albumIds.length >= MAX_ITEMS;
  const dialogOpen = hashParam in hashParams;
  const appAlert = useAppAlert();
  const router = useAppRouter();
  const confirmNavigation = useConfirmNavigation();

  const unusedAlbums = albums?.filter(({ id }) => !albumIds.includes(id));
  const hasUnusedAlbums = !!unusedAlbums?.length;
  const isDisabled = maxItemsReached || !hasUnusedAlbums;

  const createAlbumLink = ({ children }: { children: ReactNode }) => (
    <Link
      href="/create/album"
      isUnderlined
      withHoverStyle
      onClick={async ({ event }) => {
        event.preventDefault();

        if (await confirmNavigation()) {
          router.push('/create/album');
        }
      }}
    >
      {children}
    </Link>
  );

  return (
    <>
      <Box centerContent>
        <Clickable
          testId="addRelease"
          isInline
          isCentered
          withActiveStyle={!isDisabled}
          onClick={useCallback(() => {
            if (maxItemsReached) {
              appAlert({
                content: t('itemEdit.itemLimitReached'),
              });

              return;
            }

            if (!hasUnusedAlbums) {
              appAlert({
                content: (
                  <Box flexColumn gap="1rem">
                    <Text>{t('itemEdit.releases.errors.noMoreItems')}</Text>
                    <Text size="1.3rem">
                      {tx('itemEdit.releases.addReleaseHint', {
                        createAlbumLink,
                      })}
                    </Text>
                  </Box>
                ),
              });

              return;
            }

            setHashParam({ [hashParam]: '' });
          }, [maxItemsReached, hasUnusedAlbums])}
          margin="2.4rem 0 0 0"
          style={{ opacity: isDisabled ? 0.25 : 1 }}
        >
          <Text size="1.7rem" isBold centered>
            {t('itemEdit.releases.addRelease')}
          </Text>
        </Clickable>
      </Box>
      {dialogOpen && (
        <DialogBox
          onClose={() => backToBeforeFirstHash()}
          testId="addReleaseDialog"
          withOverflowGradients={false}
          renderContent={({ paddingX, close }) => {
            return (
              <>
                <Sticky top={0} zIndex={2}>
                  <DialogBoxHeader
                    title={t('itemEdit.releases.addRelease')}
                    onCloseClick={close}
                    withShadow
                  />
                </Sticky>
                <Box padding="1rem 0" tag="ul">
                  {albums
                    ?.filter(({ id }) => !albumIds.includes(id))
                    .map(({ id, name, image }) => {
                      return (
                        <ListItem
                          padding={`0 ${paddingX}`}
                          key={`addAlbum${id}`}
                          title={name}
                          height="6rem"
                          image={image}
                          fontSize="1.6rem"
                          imageSize="4em"
                          data={{ id, close }}
                          onClick={async () => {
                            await close();
                            onSubmit(id);
                          }}
                        />
                      );
                    })}
                </Box>
                <Sticky
                  bottom={0}
                  zIndex={2}
                  style={{ backgroundColor: darkTheme.background }}
                >
                  <Text padding="1rem 2rem 2rem" centered size="1.3rem" isBlock>
                    {tx('itemEdit.releases.addReleaseHint', {
                      createAlbumLink,
                    })}
                  </Text>
                </Sticky>
              </>
            );
          }}
        />
      )}
    </>
  );
};

export default ReleasesSectionEdit;
