import { memo, useMemo, useRef, useSignal } from '@teact';
import { setExtraStyles } from '@teact/teact-dom';
import { withGlobal } from '../../../../global';

import type { ApiPromoData, ApiSession } from '../../../../api/types';

import { FRESH_AUTH_PERIOD } from '../../../../config';
import { requestMutation } from '../../../../lib/fasterdom/fasterdom';
import { selectIsCurrentUserFrozen, selectIsForumPanelOpen } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { getServerTime } from '../../../../util/serverTime';
import { REM } from '../../../common/helpers/mediaDimensions';

import useEffectOnce from '../../../../hooks/useEffectOnce';
import useShowTransition from '../../../../hooks/useShowTransition';
import { useSignalEffect } from '../../../../hooks/useSignalEffect';
import { applyAnimationState, type PaneState } from '../../../middle/hooks/useHeaderPane';

import FrozenAccountPane from './FrozenAccountPane';
import GiftAuctionPane from './GiftAuctionPane';
import SuggestionPane from './SuggestionPane';
import UnconfirmedSessionPane from './UnconfirmedSessionPane';

import styles from './ChatListPanes.module.scss';

type OwnProps = {
  className?: string;
  onHeightChange: (height: number) => void;
};

type StateProps = {
  sessions: Record<string, ApiSession>;
  promoData?: ApiPromoData;
  isAccountFrozen?: boolean;
  isForumPanelOpen?: boolean;
};

const ITEM_MARGIN = 0.25 * REM;
const BOTTOM_MARGIN = 0.5 * REM;
const FALLBACK_PANE_STATE = { height: 0 };

const ChatListPanes = ({
  className,
  sessions,
  promoData,
  isAccountFrozen,
  isForumPanelOpen,
  onHeightChange,
}: OwnProps & StateProps) => {
  const [getUnconfirmedSessionHeight, setUnconfirmedSessionHeight] = useSignal<PaneState>(FALLBACK_PANE_STATE);
  const [getFrozenAccountState, setFrozenAccountState] = useSignal<PaneState>(FALLBACK_PANE_STATE);
  const [getGiftAuctionState, setGiftAuctionState] = useSignal<PaneState>(FALLBACK_PANE_STATE);
  const [getSuggestionState, setSuggestionState] = useSignal<PaneState>(FALLBACK_PANE_STATE);

  const isFirstRenderRef = useRef(true);
  const {
    shouldRender,
    ref,
  } = useShowTransition({
    isOpen: true,
    withShouldRender: true,
    noMountTransition: true,
  });

  useEffectOnce(() => {
    isFirstRenderRef.current = false;
  });

  const unconfirmedSession = useMemo(() => {
    const sessionsArray = Object.values(sessions || {});
    const current = sessionsArray.find((session) => session.isCurrent);
    if (!current || getServerTime() - current.dateCreated < FRESH_AUTH_PERIOD) return undefined;

    return sessionsArray.find((session) => session.isUnconfirmed);
  }, [sessions]);

  const canShowUnconfirmedSession = !isAccountFrozen && !isForumPanelOpen && unconfirmedSession;
  const canShowSuggestions = !isAccountFrozen && !isForumPanelOpen && !unconfirmedSession && promoData;
  const canShowGiftAuctions = !isAccountFrozen && !isForumPanelOpen;

  useSignalEffect(() => {
    const unconfirmedSessionHeight = getUnconfirmedSessionHeight();
    const frozenAccountHeight = getFrozenAccountState();
    const giftAuctionHeight = getGiftAuctionState();
    const suggestionHeight = getSuggestionState();

    // Keep in sync with the order of the panes in the DOM
    const stateArray = [
      unconfirmedSessionHeight,
      frozenAccountHeight,
      giftAuctionHeight,
      { height: giftAuctionHeight.height ? ITEM_MARGIN : 0, isSpacer: true },
      suggestionHeight,
      { height: BOTTOM_MARGIN, isSpacer: true },
    ];

    const isFirstRender = isFirstRenderRef.current;
    const totalHeight = stateArray.reduce((acc, state) => acc + state.height, 0);
    const panelsHeight = totalHeight - BOTTOM_MARGIN;

    onHeightChange(panelsHeight !== 0 ? totalHeight : 0);

    const leftColumn = document.getElementById('LeftColumn');
    if (!leftColumn) return;

    applyAnimationState({
      list: stateArray,
      noTransition: isFirstRender,
      zIndexIncrease: true,
    });

    requestMutation(() => {
      setExtraStyles(leftColumn, {
        '--chat-list-panes-height': `${totalHeight}px`,
      });
    });
  }, [getUnconfirmedSessionHeight, getFrozenAccountState, getSuggestionState, getGiftAuctionState]);

  if (!shouldRender) return undefined;

  return (
    <div
      ref={ref}
      className={
        buildClassName(
          styles.root,
          className,
        )
      }
    >
      <FrozenAccountPane
        isAccountFrozen={isAccountFrozen}
        onPaneStateChange={setFrozenAccountState}
      />
      <UnconfirmedSessionPane
        unconfirmedSession={canShowUnconfirmedSession ? unconfirmedSession : undefined}
        onPaneStateChange={setUnconfirmedSessionHeight}
      />
      <GiftAuctionPane
        canShow={canShowGiftAuctions}
        onPaneStateChange={setGiftAuctionState}
      />
      <SuggestionPane
        promoData={canShowSuggestions ? promoData : undefined}
        onPaneStateChange={setSuggestionState}
      />
    </div>
  );
};

export default memo(withGlobal<OwnProps>(
  (global): Complete<StateProps> => {
    return {
      isForumPanelOpen: selectIsForumPanelOpen(global),
      sessions: global.activeSessions.byHash,
      promoData: global.promoData,
      isAccountFrozen: selectIsCurrentUserFrozen(global),
    };
  },
)(ChatListPanes));
