import { WebComponent } from '../../webComponent/WebComponent';
import React, { useState } from 'react';
import { PresentationMode, WebComponentType } from '../../types/internal/webComponent.types';
import { withReduxStore } from '../../helpers/store/helpers';
import { RESPONSE_KEYS, UnitOnLoadResponseEvent } from '../../messages/webMessages/onLoadMessage';
import { UNAccount, UNComponentsError, UNComponentsOnLoadResponse, UNComponentsOnLoadResponseData, UNWirePayment } from '../../types/shared';
import { WebViewMessage } from '../../messages/webMessages';
import { PaymentMessage } from '../../messages/webMessages/paymentsMessage';
import { UnitComponentsMessage } from '../../messages/webMessages/unitComponentsMessages';
import { HeightEvent, PageMessage } from '../../messages/webMessages/pageMessage';
import { getWirePaymentParams, getWirePaymentScript } from './UNWirePaymentComponent.utils';
import { UNBaseView } from '../../nativeComponents/UNBaseView';
import { ensureArray } from '../../utils/onLoadMessages.utils';
import { WirePaymentCreatedEvent } from '../../messages/webMessages/wirePaymentMessage';

export interface UNWirePaymentComponentProps {
  // inputs
  accountId?: string;

  // ui
  theme?: string;
  language?: string;

  isAutoFocus?: boolean;
  initialStageBackButton?: boolean;
  finalStageDoneButton?: boolean;

  // events
  onPaymentCreated?: (data: UNWirePayment) => void;
  onLoad?: (response: UNComponentsOnLoadResponse<[UNAccount]>) => void;
  onInitialStageBackButtonClicked?: () => void;
  onFinalStageDoneButtonClicked?: () => void;
}

const UNWirePaymentComponent = (props: UNWirePaymentComponentProps) => {
  const [height, setHeight] = useState<number>(0);
  const [presentationMode, setPresentationMode] = useState<PresentationMode>(PresentationMode.Inherit);

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

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

    if (RESPONSE_KEYS.account in response) {
      const account = response[RESPONSE_KEYS.account].data;
      const paymentOnLoad: UNComponentsOnLoadResponseData<[UNAccount]> = {
        data: ensureArray(account),
      };
      props.onLoad(paymentOnLoad);
      return;
    }

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

  const handleWebViewMessage = (message: WebViewMessage) => {
    if (!message || !message.details) return;
    switch (message.type) { 
      case PaymentMessage.INITIAL_STAGE_BACK_BUTTON_CLICKED: {
        props.onInitialStageBackButtonClicked && props.onInitialStageBackButtonClicked();
        break;
      }
      case PaymentMessage.FINAL_STAGE_DONE_BUTTON_CLICKED: {
        props.onFinalStageDoneButtonClicked && props.onFinalStageDoneButtonClicked();
        break;
      }
      case PaymentMessage.PAYMENT_CREATED:
        props.onPaymentCreated && props.onPaymentCreated((message.details as WirePaymentCreatedEvent).data);
        break;
      case UnitComponentsMessage.UNIT_ON_LOAD:
        handleUnitOnLoad(message.details as UnitOnLoadResponseEvent);
        break;
      case PageMessage.PAGE_HEIGHT: {
        const currentHeight = (message.details as HeightEvent).height;
        setHeight(currentHeight);
        if (presentationMode === PresentationMode.Inherit && currentHeight === 0) {
          setPresentationMode(PresentationMode.Default);
        }
        break;
      }
    }
  };

  const style = presentationMode === PresentationMode.Inherit ? { flex: 1 } : { height: height };
  return (
    <UNBaseView style={style} fallback={<></>}>
      <WebComponent
        type={WebComponentType.wirePayment}
        presentationMode={presentationMode}
        params={getWirePaymentParams(props)}
        script={getWirePaymentScript()}
        onMessage={(message: WebViewMessage) => handleWebViewMessage(message)}
        isScrollable={true}
        theme={props.theme}
        language={props.language}
      />
    </UNBaseView>
  );
};

export default withReduxStore<UNWirePaymentComponentProps>(UNWirePaymentComponent);
