import React, { useImperativeHandle, useRef, useState } from 'react';
import { Dimensions } from 'react-native';
import {
  RequestRefreshEvent,
  RequestRenderingEvent,
  UnitMessage,
  UnitRequestRefreshEventTypes,
} from '../../messages/webMessages/unitMessages';
import type { WebViewMessage } from '../../messages/webMessages';
import { HeightEvent, PageMessage } from '../../messages/webMessages/pageMessage';
import type { UNError, UNOnLoadResponse, UNOnLoadResponseData } from '../../types/shared';
import { WebComponent } from '../../webComponent/WebComponent';
import {
  getActivityParams,
  getActivityScript,
  injectFiltersChanged,
  injectRefreshEventIfNeeded,
} from './UNActivityComponent.utils';
import type WebView from 'react-native-webview';
import type { UNActivityOnLoadData } from '../../types/shared/activity.types';
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 { setEvent } from '../../slices/SharedEventsSlice';
import { useDispatch } from 'react-redux';
import { useListenerToEvent } from '../../hooks/useListenerToEvent';
import type { UNActivityComponentPaginationType } from '../../types/shared';
import { UNBaseView } from '../../nativeComponents/UNBaseView';

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

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

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

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

const UNActivityComponent = React.forwardRef<UNActivityRef, UNActivityComponentProps>(function UNActivityComponent(props, activityRef) {
  const dispatch = useDispatch();
  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) => {
    injectFiltersChanged(webRef.current, query);
  };

  useListenerToEvent({ busEventKey: UnitMessage.UNIT_REQUEST_REFRESH, action: requestRefresh });
  useListenerToEvent({
    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 UNError);
      return;
    }

    if (RESPONSE_KEYS.authorizations in response && RESPONSE_KEYS.transactions in response) {
      // ActivityOnLoadResponse;
      const activityOnLoad: UNOnLoadResponseData<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 UnitMessage.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;

        dispatch(setEvent({ key: BottomSheetNativeMessage.REQUEST_RENDERING, data }));
        break;
      }
      case UnitMessage.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 }>
      <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);
