import Button from '@mui/material/Button'
import { AxiosError } from 'axios'
import _identity from 'lodash/identity'
import _isEmpty from 'lodash/isEmpty'
import React, { useEffect, useState } from 'react'

import {
  checkCustomerOrder,
  checkVerificationStatus,
  getNetverifyUrl,
  updateVerificationStatus,
} from '../../api'
import {
  GetNetverifyUrlResponseData,
  VerificationStatusResponseData,
} from '../../types/verification'
import { getQueryVariable, isBrowser, isJson } from '../../utils'
import Modal from '../common/ModalComponent'
import {
  VERIFICATION_MESSAGES,
  VERIFICATION_PROVIDERS,
  VERIFICATION_STATUSES,
} from './constants'

interface IDVerificationProps {
  onGetVerifyUrlSuccess?: (response: GetNetverifyUrlResponseData) => void;
  onGetVerifyUrlError?: (error: AxiosError) => void;

  onGetVerificationStatusSuccess?: (response: {
    data: VerificationStatusResponseData;
  }) => void;
  onGetVerificationStatusError?: (error: AxiosError) => void;

  onVerificationMessageModalClose?: (status: string | null) => void;

  onPassVerificationStepsSuccess?: () => void;
  onPassVerificationStepsError?: (error: AxiosError | null) => void;
}

export const IDVerification = (props: IDVerificationProps) => {
  const {
    onGetVerifyUrlSuccess = _identity,
    onGetVerifyUrlError = _identity,

    onGetVerificationStatusSuccess = _identity,
    onGetVerificationStatusError = _identity,

    onVerificationMessageModalClose = _identity,

    onPassVerificationStepsSuccess = _identity,
    onPassVerificationStepsError = _identity,
  } = props

  const [loadingStatus, setLoadingStatus] = useState(true)
  const [verificationStatus, setVerificationStatus] = useState<string | null>(null)
  const [showModal, setShowModal] = useState(false)
  const [netverifyUrl, setNetverifyUrl] = useState<string | null>(null)
  const [provider, setProvider] = useState<string | null>(null)
  const [hasError, setHasError] = useState<boolean>(false)
  const [lastError, setLastError] = useState(null)
  const [modalData, setModalData] = useState({
    message: '',
    hideCancelBtn: true,
    displaModal: false,
  })

  const isAccountVerifiedOrPending =
    (verificationStatus === VERIFICATION_STATUSES.APPROVED ||
      verificationStatus === VERIFICATION_STATUSES.PENDING) &&
    verificationStatus !== VERIFICATION_STATUSES.WRONG_CUSTOMER

  const handleClose = () => {
    setModalData({
      message: '',
      displaModal: false,
      hideCancelBtn: true,
    })

    onVerificationMessageModalClose(verificationStatus)
  }

  useEffect(() => {
    const callbackNetVerify = async (e: any) => {
      // Stripe Events
      if (e.data && e.origin === 'https://verify.stripe.com') {
        const { data } = e
        if (data.type === 'STRIPE_IDENTITY_CLOSE') {
          await getUrl()
          setShowModal(false)
          if (hasError) {
            setHasError(false)
            onPassVerificationStepsError(lastError)
          } else {
            setHasError(false)
            onPassVerificationStepsSuccess()
          }
        } else if (data.type === 'STRIPE_IDENTITY_ERROR') {
          setHasError(true)
          setLastError(data)
        }
      }

      if (e.data && isJson(e.data)) {
        try {
          const result = JSON.parse(e.data)
          if (
            result.payload &&
            (result.payload.value === 'success' ||
              result.payload.transactionStatus === 'SUCCESS')
          ) {
            await updateVerificationStatus()
            onPassVerificationStepsSuccess()
          } else if (
            result.payload &&
            (result.payload.value === 'error' ||
              result.payload.transactionStatus === 'ERROR')
          ) {
            setShowModal(false)
            onPassVerificationStepsError(result.payload)
          }
        } catch (e) {
          onPassVerificationStepsError(e)
        }
      }
    }

    window.addEventListener('message', callbackNetVerify)

    return () => {
      window.removeEventListener('message', callbackNetVerify)
    }
  }, [])

  const getUrl = async () => {
    try {
      const urlResponse = await getNetverifyUrl()
      setNetverifyUrl(urlResponse.netverifyUrl)
      setProvider(urlResponse.provider)
      onGetVerifyUrlSuccess(urlResponse)
    } catch (error) {
      onGetVerifyUrlError(error)
    }
  }

  useEffect(() => {
    let intervalId: any = null
    const orderHash = getQueryVariable('order_hash') || ''

    const getVerificationStatus = async () => {
      try {
        let verificationStatus = null
        // Gets te current status of the variable without modifying it
        setVerificationStatus(status => {
          verificationStatus = status
          return status
        })
        let provider = null
        // Gets te current status of the variable without modifying it
        setProvider(state => {
          provider = state
          return provider
        })
        let verifyUrl = null
        // Gets te current status of the variable without modifying it
        setNetverifyUrl(state => {
          verifyUrl = state
          return state
        })
        const statusResponse = await checkVerificationStatus()
        const { status } = statusResponse.data.attributes
        const isApproved = status === VERIFICATION_STATUSES.APPROVED

        if (verificationStatus !== status) {
          setVerificationStatus(status)
          setModalData({
            displaModal: isApproved || status === VERIFICATION_STATUSES.FAILED,
            hideCancelBtn: true,
            message: isApproved
              ? VERIFICATION_MESSAGES.APPROVED
              : status === VERIFICATION_STATUSES.FAILED
              ? VERIFICATION_MESSAGES.FAILED
              : status,
          })
        }
        if (
          provider === VERIFICATION_PROVIDERS.STRIPE &&
          verifyUrl === null &&
          !isApproved
        ) {
          getUrl()
        }
        onGetVerificationStatusSuccess(statusResponse)
      } catch (error) {
        onGetVerificationStatusError(error)
      } finally {
        setLoadingStatus(false)
      }
    }

    const getCustomerOrderStatus = async () => {
      const customerOrderResponse = await checkCustomerOrder(orderHash)
      return customerOrderResponse
    }

    const makeRequests = async () => {
      try {
        if (orderHash) {
          await getCustomerOrderStatus()
        }
        getUrl()
        getVerificationStatus()

        // Check the verification status every 30 seconds
        intervalId = setInterval(() => {
          getVerificationStatus()
        }, 10000)
      } catch (error) {
        if (error.response?.data?.message === VERIFICATION_MESSAGES.WRONG_CUSTOMER) {
          setVerificationStatus(VERIFICATION_STATUSES.WRONG_CUSTOMER)
          setModalData({
            displaModal: true,
            hideCancelBtn: true,
            message: VERIFICATION_MESSAGES.WRONG_CUSTOMER,
          })
        }
      }
    }

    makeRequests()

    // Clear the interval when the component unmounts
    return () => clearInterval(intervalId)
  }, [])

  const iframe = (netverifyUrl: string) => {
    // eslint-disable-next-line max-len
    const iframe = `<iframe allowFullScreen id="verificationIframe" frameBorder="0" width="100%" height="570px" allow="camera;fullscreen;accelerometer;gyroscope;magnetometer" src="${netverifyUrl}"></iframe>`
    return {
      __html: iframe,
    }
  }

  useEffect(() => {
    const orderHash = getQueryVariable('order_hash')

    if (isBrowser) {
      const checkoutData = JSON.parse(window.localStorage.getItem('checkoutData') || '{}')
      if (_isEmpty(checkoutData) && orderHash) {
        window.localStorage.setItem('checkoutData', JSON.stringify({ hash: orderHash }))
      }
    }
  }, [])

  return (
    <div>
      <h2 className="page-header">Account Verification</h2>
      {loadingStatus ? null : (
        <>
          {!isAccountVerifiedOrPending && (
            <div className="verify-message">
              To complete the purchase, please verify your identity.
            </div>
          )}
          {verificationStatus === VERIFICATION_STATUSES.APPROVED && (
            <div className="verify-message">{VERIFICATION_MESSAGES.APPROVED}</div>
          )}
          {(verificationStatus === VERIFICATION_STATUSES.PENDING ||
            (provider === VERIFICATION_PROVIDERS.STRIPE &&
              netverifyUrl === null &&
              verificationStatus !== VERIFICATION_STATUSES.APPROVED)) && (
            <div className="verify-message">{VERIFICATION_MESSAGES.PENDING}</div>
          )}
          {!isAccountVerifiedOrPending && netverifyUrl !== null && (
            <Button
              type="button"
              variant="contained"
              className="verify-button"
              onClick={() => {
                setShowModal(true)
              }}
            >
              Verify
            </Button>
          )}
        </>
      )}

      {modalData.displaModal && (
        <Modal
          modalClassName="verification-message-modal"
          actions={[
            {
              id: 'ok',
              label: 'Ok',
              variant: 'contained',
              onClick: handleClose,
            },
          ]}
        >
          <div className="verify-message">{modalData.message}</div>
        </Modal>
      )}

      {showModal && (
        <Modal
          modalClassName="id-verification-modal"
          actions={[
            {
              id: 'close',
              label: 'Close',
              variant: 'contained',
              onClick: () => {
                setShowModal(false)
              },
            },
          ]}
        >
          <div dangerouslySetInnerHTML={iframe(netverifyUrl || '')} />
        </Modal>
      )}
    </div>
  )
}
