import React, { useImperativeHandle, useRef, useState } from 'react';
import { Dimensions } from 'react-native';
import {
  RequestRefreshEvent,
  RequestRenderingEvent,
  UnitComponentsMessage,
  UnitRequestRefreshEventTypes,
} from '../../messages/webMessages/unitComponentsMessages';
import type { WebViewMessage } from '../../messages/webMessages';
import { HeightEvent, PageMessage } from '../../messages/webMessages/pageMessage';
import type { 
  UNComponentsError, 
  UNComponentsOnLoadResponse, 
  UNComponentsOnLoadResponseData, 
  UNActivityOnLoadData, 
  UNActivityComponentPaginationType 
} from '../../types/shared';
import { WebComponent } from '../../webComponent/WebComponent';
import {
  getActivityParams,
  getActivityScript,
  injectActivityFiltersChanged,
  injectRefreshEventIfNeeded,
} from './UNActivityComponent.utils';
import type WebView from 'react-native-webview';
import { RESPONSE_KEYS, UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
import { ActivityMessage } from '../../messages/webMessages/activityMessage';
import {
  BottomSheetRenderingType,
} from '../../types/internal/bottomSheet.types';
import type { BottomSheetSlotData, SlotRendering } from '../../types/internal/bottomSheet.types';
import { PresentationMode, WebComponentType } from '../../types/internal/webComponent.types';
import { BottomSheetNativeMessage } from '../../messages/nativeMessages/bottomSheetMessage';
import { withReduxStoreAndRefForwarding } from '../../helpers/store/helpers';
import { eventBus } from '../../utils/eventBus';
import { useEventListener } from '../../hooks/useEventListener';
import { UNBaseView } from '../../nativeComponents/UNBaseView';

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

export interface UNActivityComponentProps {
  // inputs
  accountId?: string;
  queryFilter?: string;

  // ui
  theme?: string;
  language?: string;
  hideFilterButton?: boolean;
  hideTitle?: boolean;
  hideBackToTop?: boolean;
  paginationType?: UNActivityComponentPaginationType;
  transactionsPerPage?: number;
  showDeclinedActivity?: boolean;
  showCsvDownload?: boolean;
  // event
  onLoad?: (response: UNComponentsOnLoadResponse<UNActivityOnLoadData>) => void;
}

export interface UNActivityRef {
  refresh: () => void;
}

const UNActivityComponent = React.forwardRef<UNActivityRef, UNActivityComponentProps>(function UNActivityComponent(props, activityRef) {
  const webRef = useRef<WebView>(null);
  const [defaultHeight, setDefaultHeight] = useState<number>();

  const requestRefresh = (data: RequestRefreshEvent) => {
    injectRefreshEventIfNeeded(webRef.current, data);
  };

  useImperativeHandle(activityRef, () => ({
    refresh() {
      requestRefresh({
        type: UnitRequestRefreshEventTypes.REQUEST_REFRESH_EVENT,
        refEvent: undefined,
        dependencies: [WebComponentType.activity.valueOf()],
        resourceId: '',
      });
    },
  }));

  const dispatchActivityFiltersChanged = (query: string) => {
    injectActivityFiltersChanged(webRef.current, query);
  };

  useEventListener({ busEventKey: UnitComponentsMessage.UNIT_REQUEST_REFRESH, action: requestRefresh });
  useEventListener({
    busEventKey: ActivityMessage.UNIT_ACTIVITY_FILTERS_CHANGED,
    action: dispatchActivityFiltersChanged,
  });

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

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

    if (RESPONSE_KEYS.authorizations in response) {
      // ActivityOnLoadResponse;
      const activityOnLoad: UNComponentsOnLoadResponseData<UNActivityOnLoadData> = {
        data: {
          [RESPONSE_KEYS.authorizations]: response[RESPONSE_KEYS.authorizations].data,
          [RESPONSE_KEYS.transactions]: response[RESPONSE_KEYS.transactions]?.data,
        },
      };
      props.onLoad(activityOnLoad);
      return;
    }

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

  const handleWebViewMessage = (message: WebViewMessage) => {
    switch (message.type) {
      case UnitComponentsMessage.UNIT_REQUEST_RENDERING: {
        const slotData: BottomSheetSlotData = {
          componentName: WebComponentType.activity,
          componentResourceId: props.accountId,
          requestRenderingEvent: message.details as RequestRenderingEvent,
        };

        const data = {
          type: BottomSheetRenderingType.Slot,
          data: slotData,
        } as SlotRendering;

        eventBus.emit(BottomSheetNativeMessage.REQUEST_RENDERING, data);
        break;
      }
      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;
      }
    }
  };

  const style = defaultHeight ? { height: defaultHeight } : { flex: 1 };

  return (
    <UNBaseView style={style} onLoadError={ handleUnitOnLoad } fallback={<></>}>
      <WebComponent
        ref={webRef}
        type={WebComponentType.activity}
        presentationMode={PresentationMode.Inherit}
        params={getActivityParams(props)}
        onMessage={(message: WebViewMessage) => handleWebViewMessage(message)}
        nestedScrollEnabled={true}
        theme={props.theme}
        language={props.language}
        script={getActivityScript()}
      />
    </UNBaseView>
  );
});

export default withReduxStoreAndRefForwarding<UNActivityComponentProps, UNActivityRef>(UNActivityComponent);
