import React, { useRef, useState } from 'react';
import { Dimensions } from 'react-native';
import type { WebViewMessage } from '../../messages/webMessages';
import { HeightEvent, PageMessage } from '../../messages/webMessages/pageMessage';
import { WebComponent } from '../../webComponent/WebComponent';

import type WebView from 'react-native-webview';

import { PresentationMode, WebComponentType } from '../../types/internal/webComponent.types';
import { withReduxStore } from '../../helpers/store/helpers';
import { getMultipleCardsParams, getMultipleCardsScript, injectCardCreated, injectCardStatusChangedEvent, injectMultipleCardsFiltersChanged } from './UNMultipleCardsComponent.utils';
import { RequestRenderingEvent, UnitComponentsMessage } from '../../messages/webMessages/unitComponentsMessages';
import type { UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
import { RESPONSE_KEYS } from '../../messages/webMessages/onLoadMessage';
import type {
  UNCard,
  UNComponentsError,
  UNMultipleCardsComponentPaginationType,
  UNMultipleCardsOnLoadData,
  UNComponentsOnLoadResponse,
  UNComponentsOnLoadResponseData,
} from '../../types/shared';
import { MultipleCardsCardClickedEvent, MultipleCardsMessage } from '../../messages/webMessages/multipleCardsMessage';
import { UNBaseView } from '../../nativeComponents/UNBaseView';
import { useEventListener } from '../../hooks/useEventListener';
import { CardMessage } from '../../messages/webMessages/cardMessage';
import { BottomSheetRenderingType, BottomSheetSlotData, SlotRendering } from '../../types/internal/bottomSheet.types';
import { eventBus } from '../../utils/eventBus';
import { BottomSheetNativeMessage } from '../../messages/nativeMessages/bottomSheetMessage';

const DEFAULT_HEIGHT = Dimensions.get('window').height * 0.5;

export interface UNMultipleCardsComponentProps {
  // ui
  paginationType?: UNMultipleCardsComponentPaginationType;
  cardsPerPage?: number;
  disableCardClick?: boolean;
  isRowItemClickable?: boolean;
  showSeeAllCardsLink?: boolean;
  theme?: string;
  language?: string;
  queryFilter?: string;
  hideTitle?: boolean;
  hideBackToTop?: boolean;

  // events
  onLoad?: (response: UNComponentsOnLoadResponse<UNMultipleCardsOnLoadData>) => void;
  onCardClicked?: (card: UNCard) => void;
}

const UNMultipleCardsComponent = (props: UNMultipleCardsComponentProps) => {
  const webRef = useRef<WebView>(null);
  const [defaultHeight, setDefaultHeight] = useState<number>();

  const dispatchCardStatusChanged = (card: UNCard) => {
    injectCardStatusChangedEvent(webRef.current, card);
  };

  const dispatchMultipleCardsFiltersChanged = (query: string) => {
    injectMultipleCardsFiltersChanged(webRef.current, query);
  };

  const dispatchCardCreated = (card: UNCard) => {
    injectCardCreated(webRef.current, card);
  };

  useEventListener({ 
    busEventKey: CardMessage.CARD_STATUS_CHANGED, 
    action: dispatchCardStatusChanged 
  });
  useEventListener({
    busEventKey: MultipleCardsMessage.UNIT_MULTIPLE_CARDS_FILTERS_CHANGED,
    action: dispatchMultipleCardsFiltersChanged,
  });
  useEventListener({
    busEventKey: CardMessage.CARD_CREATED,
    action: dispatchCardCreated,
  });

  const cardClicked = (card: UNCard) => {
    if (props.onCardClicked) {
      props.onCardClicked(card);
    }
  };

  const handleUnitOnLoad = (response: UnitOnLoadResponseEvent) => {
    if (!props.onLoad) {
      return;
    }

    if (RESPONSE_KEYS.errors in response) {
      props.onLoad(response as UNComponentsError);
      return;
    }

    if (RESPONSE_KEYS.cards in response) {
      props.onLoad(response[RESPONSE_KEYS.cards] as UNComponentsOnLoadResponseData<UNMultipleCardsOnLoadData>);
      return;
    }

    console.error('On Load Error: unexpected response type');
    return;
  };

  const handleWebViewMessage = (message: WebViewMessage) => {
    if (!message || !message.details) return;
    switch (message.type) {
      case UnitComponentsMessage.UNIT_ON_LOAD:
        handleUnitOnLoad(message.details as UnitOnLoadResponseEvent);
        break;
      case PageMessage.PAGE_HEIGHT: {
        const currentHeight = (message.details as HeightEvent).height;
        currentHeight === 0 && setDefaultHeight(DEFAULT_HEIGHT);
        break;
      }
      case MultipleCardsMessage.UNIT_MULTIPLE_CARDS_CARD_CLICKED: {
        cardClicked(message.details as MultipleCardsCardClickedEvent);
        break;
      }
      case UnitComponentsMessage.UNIT_REQUEST_RENDERING: {
        const slotData: BottomSheetSlotData = {
          componentName: WebComponentType.multipleCards,
          componentResourceId: undefined,
          requestRenderingEvent: message.details as RequestRenderingEvent,
        };
      
        const data = {
          type: BottomSheetRenderingType.Slot,
          data: slotData,
        } as SlotRendering;
        eventBus.emit(BottomSheetNativeMessage.REQUEST_RENDERING, data);
        break;
      }
    }
  };

  const style = defaultHeight ? { height: defaultHeight } : { flex: 1};
  return (
    <UNBaseView style={style} onLoadError={ handleUnitOnLoad } fallback={<></>}>
      <WebComponent
        ref={webRef}
        type={WebComponentType.multipleCards}
        presentationMode={PresentationMode.Inherit}
        params={getMultipleCardsParams(props)}
        script={getMultipleCardsScript()}
        onMessage={(message: WebViewMessage) => handleWebViewMessage(message)}
        nestedScrollEnabled={true}
        theme={props.theme}
        language={props.language}
      />
    </UNBaseView>
  );
};

export default withReduxStore<UNMultipleCardsComponentProps>(UNMultipleCardsComponent);