import React, { useMemo, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { FiltersMap } from '@wix/bex-core';
import { Box, Loader, Text, TextButton } from '@wix/design-system';
import { PickerListItemProps } from '../PickerListItemProps';
import {
  PickerContentBaseWrapped,
  PickerContentBaseWrappedProps,
} from './PickerContentBaseWrapped';
import { AdditionalStepState, PickerContentState } from '../../state';
import { ChevronLeft } from '@wix/wix-ui-icons-common';
import { st, classes } from './PickerContentAdditionalStep.st.css.js';

export interface PickerContentAdditionalStepProps<T>
  extends Partial<PickerContentBaseWrappedProps> {
  /** When true, the picker will start directly on the additional step, skipping the first selection step. The back button will also be hidden. */
  autoAdditionalStepOnInitialSelect?: boolean;

  /** The additional step title */
  additionalStepTitle?: string;

  /** The additional step subtitle */
  additionalStepSubtitle?: string;

  /** Defines a function that returns a component to render in the additional step content area, if `hasAdditionalStep` returns `false` this prop is ignored. */
  renderAdditionalStepContent?: (props: { item: T }) => JSX.Element;

  /** Indicates if selected item has additional step or not */
  hasAdditionalStep?: (props: { item: T }) => boolean;

  /** Defines a callback function just before primaryButtonOnClick callback, returned value will be added as `additionalStepData` in onSelect payload */
  onBeforeSelectAdditionalStep?: () => Promise<unknown>;

  /** Defines a callback function after user clicks on the continue button to additional step content */
  continueButtonOnClick?: (props: { item: T }) => void;

  /** Defines a callback function after user clicks on the back button in the additional step content */
  backButtonOnClick?: (props: { item: T }) => void;

  /** Additional steps modal content overrides */
  additionalStepOverrides?: {
    extraNode?: React.ReactNode;
    extraText?: string;
    subtitle?: string;
    image?: React.ReactNode;
    enablePrimaryButton?: boolean;
  };
}

interface PickerContentAdditionalStepStateProps<T, F extends FiltersMap> {
  pickerContentState: PickerContentState<T, F>;
  renderItem: (item: T, index: number) => Partial<PickerListItemProps>;
  onBackButtonClick: () => void;
}

export type PickerContentAdditionalStepFullProps<
  T,
  F extends FiltersMap = FiltersMap,
> = PickerContentAdditionalStepProps<T> &
  PickerContentAdditionalStepStateProps<T, F>;

const AdditionalStepContentRenderer = <T,>({
  renderAdditionalStepContent,
  item,
}: {
  renderAdditionalStepContent?: (props: { item: T }) => JSX.Element;
  item: T;
}) => renderAdditionalStepContent?.({ item }) ?? null;

function _PickerContentAdditionalStep<T, F extends FiltersMap = FiltersMap>(
  props: PickerContentAdditionalStepFullProps<T, F>,
) {
  const {
    pickerContentState,
    renderItem,
    renderAdditionalStepContent,
    additionalStepTitle,
    additionalStepSubtitle,
    primaryButtonOnClick,
    secondaryButtonOnClick,
    onCloseButtonClick,
    onBeforeSelectAdditionalStep,
    onBackButtonClick,
    additionalStepOverrides = {},
    primaryButtonText,
    autoAdditionalStepOnInitialSelect,
    height, // extract from rest to disable overrides
    ...rest
  } = props;

  const [state] = useState(
    () =>
      (pickerContentState.additionalStep = new AdditionalStepState({
        collection: pickerContentState.picker.collection,
      })),
  );

  const selectedKeyedItem = state.selectedKeyedItem;

  const renderedItemProps = useMemo(() => {
    if (!selectedKeyedItem) {
      return {
        title: '',
        subtitle: '',
      };
    }
    const { item, index } = selectedKeyedItem;
    const renderProps = renderItem(item, index);

    return {
      title: state.collection.itemName(item),
      ...renderProps,
    };
  }, [selectedKeyedItem]);

  const {
    collection: { translate: t },
  } = state;

  const suffixNode = useMemo(() => {
    return [
      additionalStepOverrides.extraNode,
      additionalStepOverrides.extraText,
      renderedItemProps.extraNode,
      renderedItemProps.extraText,
    ].find((node) => node !== undefined);
  }, [
    renderedItemProps,
    additionalStepOverrides.extraNode,
    additionalStepOverrides.extraText,
  ]);

  renderedItemProps.image =
    additionalStepOverrides?.image || renderedItemProps.image;
  renderedItemProps.subtitle =
    additionalStepOverrides?.subtitle || renderedItemProps.subtitle;

  const enablePrimaryButton =
    additionalStepOverrides?.enablePrimaryButton || false;

  return (
    <PickerContentBaseWrapped
      {...rest}
      primaryButtonOnClick={async () => {
        state.isLoading = true;
        if (onBeforeSelectAdditionalStep) {
          try {
            state.isLoading = true;
            state.additionalData = await onBeforeSelectAdditionalStep?.();
            primaryButtonOnClick?.();
          } catch (err) {
            console.error(err);
            state.isLoading = false;
          }
        } else {
          primaryButtonOnClick?.();
        }
      }}
      secondaryButtonOnClick={secondaryButtonOnClick}
      onCloseButtonClick={onCloseButtonClick}
      title={additionalStepTitle}
      subtitle={additionalStepSubtitle}
      primaryButtonText={
        state.isLoading ? <Loader size="tiny" /> : primaryButtonText
      }
      secondaryButtonText={t('cairo.cancel.button')}
      primaryButtonProps={{
        disabled: state.isLoading || !enablePrimaryButton,
      }}
      sideActions={
        autoAdditionalStepOnInitialSelect ? undefined : (
          <TextButton
            prefixIcon={<ChevronLeft />}
            dataHook="back-button"
            onClick={() => onBackButtonClick()}
          >
            {t('cairo.pickerModal.back.button')}
          </TextButton>
        )
      }
    >
      <Box
        direction="vertical"
        paddingLeft="SP5"
        paddingRight="SP5"
        paddingBottom="SP4"
        gap="SP4"
        overflow="auto"
        height="100%"
        dataHook="additional-step-content"
      >
        <Box direction="vertical">
          <Box gap="SP3">
            <Box align="center">{renderedItemProps.image}</Box>
            <div className={st(classes.titles)}>
              <Box>
                <Text dataHook="title" ellipsis>
                  {renderedItemProps.title}
                </Text>
              </Box>
              <Box>
                <Text secondary light dataHook="subtitle" ellipsis>
                  {renderedItemProps.subtitle}
                </Text>
              </Box>
            </div>
            {suffixNode !== undefined && (
              <div className={st(classes.suffix)}>
                {typeof suffixNode === 'string' ? (
                  <Text secondary dataHook="suffix-text">
                    {suffixNode}
                  </Text>
                ) : (
                  <Box dataHook="suffix-node">{suffixNode}</Box>
                )}
              </div>
            )}
          </Box>
        </Box>
        <Box
          direction="vertical"
          minHeight="100px"
          width="100%"
          dataHook="additional-step-widget"
          position="relative"
        >
          {selectedKeyedItem && (
            <AdditionalStepContentRenderer
              renderAdditionalStepContent={renderAdditionalStepContent}
              item={selectedKeyedItem.item}
            />
          )}
        </Box>
      </Box>
    </PickerContentBaseWrapped>
  );
}

export const PickerContentAdditionalStep = observer(
  _PickerContentAdditionalStep,
);
