import { memo, useEffect, useMemo, useState } from 'react';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import classnames from 'classnames';
import Debug from 'debug';

import type { MappedUser } from '~/src/lib/songwhipApi/users/types';
import type { ReactNode } from 'react';
import type { SideNavItem, SideNavItemPrimary } from '../types';

import { removePathSuffix } from '~/lib/router2/utils';
import Box from '~/src/components/Box';
import Clickable, { ClickableOnClick } from '~/src/components/Clickable';
import CrossIcon from '~/src/components/Icon/CrossIcon';
import Image from '~/src/components/Image';
import Link from '~/src/components/Link2';
import LogoSongwhip from '~/src/components/Logos/LogoSongwhip';
import Scroller2 from '~/src/components/Scroller2';
import Text from '~/src/components/Text';
import { toPublicEndpoint } from '~/src/lib/getPublicEndpoint';
import { useI18n } from '~/src/lib/i18n';
import toSizedImageUrlNext from '~/src/lib/toSizedImageUrlNext';
import getActiveItem from './getActiveItem';
import getItemCss from './getItemCss';
import PrimaryItems from './PrimaryItems';

// TODO: place this in nav somewhere
// const commitHash = process.env.NEXT_PUBLIC_GIT_COMMIT_SHA;
// const versionId = commitHash && `Version ${commitHash.slice(0, 7)}`;

const IS_SONGWHIP_AUTH_ENABLED = process.env.ENABLE_SONGWHIP_AUTH === '1';

const debug = Debug('songwhip/SideNav');
const PICKERS_HEIGHT = '2.2em';
const HORIZONTAL_PADDING = '2.2em';

const CountryPickerDynamic = dynamic(
  () => import('./Pickers').then((m) => m.CountryPicker),
  {
    ssr: false,
  }
);

const LanguagePickerDynamic = dynamic(
  () => import('./Pickers').then((m) => m.LanguagePicker),
  {
    ssr: false,
  }
);

const SideNavInternal = memo<{
  onCloseClick: () => void;
  onItemClick: ClickableOnClick<unknown>;
  isVisible: boolean;
  primaryItems: SideNavItemPrimary[];
  secondaryItems: SideNavItem[];
  user: MappedUser | undefined;
  renderAfter?: (params: { hasBeenVisible: boolean }) => ReactNode;
  homePath: string;
}>(
  ({
    onCloseClick,
    onItemClick,
    isVisible,
    renderAfter,
    user,
    primaryItems,
    secondaryItems,
    homePath,
  }) => {
    const [hasBeenVisible, setHasBeenVisible] = useState(false);

    // We use `hasBeenVisible` to trigger the render of some lazy components
    // the first time the SideNav is opened. We then keep them in the tree to
    // avoid unnecessary mounts/unmounts each time the SideNav is opened/closed.
    useEffect(() => {
      if (isVisible && !hasBeenVisible) {
        debug('first visible');
        setHasBeenVisible(true);
      }
    }, [isVisible]);

    const itemCss = getItemCss();
    const { t } = useI18n('app');

    // we have to use next/router here as AppRouter context
    // doesn't appear to trigger a re-render of this component
    // we may need to change the AppRouterContext value to be
    // a different object whenever the route changes
    const router = useRouter();

    const activeItem = getActiveItem({
      activePathname: removePathSuffix(router.asPath),
      items: [...primaryItems, ...secondaryItems],
    });

    return useMemo(
      () => (
        <Box flexColumn fullHeight>
          <Scroller2
            flexGrow
            contentStyle={{ display: 'flex', flexDirection: 'column' }}
            withOverflowGradients
          >
            <Box
              flexRow
              alignCenter
              padding={`0 ${HORIZONTAL_PADDING}`}
              margin="2.6em 0 0"
              height="2.7em"
            >
              <Clickable
                padding="0 1.4em 0 0"
                onClick={onCloseClick}
                testId="closeSideNav"
                title="Close menu"
                isInline
              >
                <CrossIcon size="2.4em" opacity={0.6} />
              </Clickable>
              <Clickable href={homePath} title={t('sideNav.goToHomepage')}>
                <LogoSongwhip size="2.2em" />
              </Clickable>
              {IS_SONGWHIP_AUTH_ENABLED &&
                (!user ? (
                  <Clickable
                    isInline
                    margin="0 0 0 auto"
                    testId="loginButton"
                    onClick={() => {
                      router.push(
                        `/login?callbackUrl=${encodeURIComponent(
                          location.pathname
                        )}`
                      );
                    }}
                  >
                    <Text isBold size="1.6em">
                      {t('sideNav.login')}
                    </Text>
                  </Clickable>
                ) : (
                  user.image && (
                    <Clickable
                      width="2.9em"
                      href="/account"
                      margin="0 0 0 auto"
                      title="Visit account"
                      withHoverOpacityFrom={0.88}
                    >
                      <Image
                        src={
                          isVisible
                            ? toSizedImageUrlNext({
                                url: user?.image,
                                width: 100,
                              })
                            : undefined
                        }
                        alt="User image"
                        testId="userImage"
                        isLazy
                        aspect={1}
                        style={{
                          borderRadius: '50%',
                          border: 'solid 0.15em #bbb',
                          background: '#222',
                        }}
                      />
                    </Clickable>
                  )
                ))}
            </Box>
            <Box tag="nav" margin="2em 0 0" flexGrow flexColumn>
              <PrimaryItems
                activeItem={activeItem}
                items={primaryItems}
                onItemClick={onItemClick}
              />
              <Box padding="1.7em 0 0" />
              <Box tag="ul" flexGrow padding="0 1.2em">
                {secondaryItems.map((item) => {
                  const { key, href, text, onClick = undefined, testId } = item;
                  const isActive = item === activeItem;

                  return (
                    <Box key={key} tag="li">
                      <Clickable
                        href={href}
                        testId={testId || `sideNavSecondaryItem:${href}`}
                        withFocusStyle={false}
                        autoFocus={isActive}
                        flexBox
                        padding={`0.95em 1em`}
                        positionRelative
                        onClick={async (params) => {
                          if (onClick) {
                            await onClick();
                          }

                          onItemClick(params);
                        }}
                        className={classnames(itemCss.className, 'item', {
                          isActive,
                        })}
                      >
                        <Text size="1.8em" positionRelative>
                          {text}
                        </Text>
                      </Clickable>
                    </Box>
                  );
                })}
                {itemCss.styles}
              </Box>
              <Box padding={`3em 2em 2em`}>
                <Box margin="0.7em 0 0" height={PICKERS_HEIGHT}>
                  {hasBeenVisible && (
                    <Box flexRow>
                      <CountryPickerDynamic
                        height={PICKERS_HEIGHT}
                        margin="0 0.7em 0 0"
                      />
                      <LanguagePickerDynamic height={PICKERS_HEIGHT} />
                    </Box>
                  )}
                </Box>
                <Text size="1.2em" color="#777" margin="0.2em 0 0">
                  © {new Date().getFullYear()} Songwhip •{' '}
                  <Link
                    testId="privacyLink"
                    href={toPublicEndpoint('/privacy/sme')}
                    withHoverStyle
                  >
                    {t('labels.privacy')}
                  </Link>{' '}
                  &amp;{' '}
                  <Link href="/terms" withHoverStyle>
                    {t('labels.terms')}
                  </Link>
                </Text>
              </Box>
            </Box>
          </Scroller2>
          {renderAfter && renderAfter({ hasBeenVisible })}
        </Box>
      ),
      [activeItem, renderAfter, hasBeenVisible, isVisible, user]
    );
  }
);

export default SideNavInternal;
