import { PaymentSelectors, usePaymentDispatch, ValidationSelectors, useValidationDispatch } from '@greenpay/redux'
import { PlaidIcon } from '@greenpay/utils'
import { Button, CircularProgress, Divider, FormHelperText, IconButton, Paper, Typography } from '@mui/material'
import AccountBalanceIcon from '@mui/icons-material/AccountBalance'
import CheckCircleIcon from '@mui/icons-material/CheckCircle'
import { useSelect } from '@wordpress/data'
import { useEffect, useLayoutEffect, useState } from '@wordpress/element'
import PlaidWidget from './PlaidWidget'
import TanFlow from './TanFlow'

import styles from './Plaid.module.scss'

const PlaidComponent: React.FC = () => {
	const plaid = useSelect((select) => (select('green-pay/payment') as PaymentSelectors).getPlaid(), [])
	const debit = useSelect((select) => (select('green-pay/payment') as PaymentSelectors).getDebit(), [])
	const accountMask = useSelect((select) => (select('green-pay/payment') as PaymentSelectors).getAccountMask(), [])
	const plaidTouched = useSelect(
		(select) => (select('green-pay/validation') as ValidationSelectors).getPlaidTouched(),
		[],
	)
	const plaidError = useSelect(
		(select) => (select('green-pay/validation') as ValidationSelectors).getPlaidError(),
		[],
	)
	const tanStatus = useSelect((select) => (select('green-pay/validation') as ValidationSelectors).getTanStatus(), [])
	const plaidOpen = useSelect((select) => (select('green-pay/validation') as ValidationSelectors).getPlaidOpen(), [])

	const { setMethod, setDebit, setAccountMask } = usePaymentDispatch()
	const { setPlaidError, setPlaidTouched, setPlaidOpen } = useValidationDispatch()

	const [showWidget, setShowWidget] = useState(false)

	/**
	 * Hook to respond to the Plaid data returned from the widget.
	 * useLayoutEffect so this runs synchronously after the render with new plaid,
	 * before paint or other effects, avoiding timing/remount issues.
	 */
	useLayoutEffect(() => {
		if (!plaid) return

		if (!plaid.success) {
			setPlaidTouched(true)
			setPlaidError('Bank login was unsuccessful, please try again.')
			return
		}

		if (plaid.isTAN && !tanStatus) {
			setPlaidTouched(true)
			setPlaidError('Bank account requires additional user verification.')
			return
		}

		if (plaid.success && !plaid.isTAN) {
			setAccountMask(plaid.mask ?? '')
			setMethod('plaid')
		}
	}, [plaid, tanStatus, setPlaidTouched, setPlaidError, setMethod, setAccountMask])

	// Hook to handle succesful TAN dialog events. Set synchronously to avoid race with remount.
	useEffect(() => {
		if (!tanStatus || !debit) return

		setPlaidError('')
		setMethod('debit')
		if (debit.accountNumber) {
			setAccountMask(debit.accountNumber.slice(-4))
			setDebit(debit)
		}
	}, [tanStatus, debit, setPlaidError, setMethod, setDebit, setAccountMask])

	useEffect(() => {
		setShowWidget(plaidOpen)
	}, [plaidOpen])

	const handleWidget = (widgetVisible: boolean) => {
		setPlaidOpen(widgetVisible)
		setShowWidget(widgetVisible)
	}

        // TAN state: Display TAN validation call to action first
        if (plaid && plaid.isTAN && !tanStatus) {
                return <TanFlow institution={plaid.institution} helpLink={plaid.helpLink} />
        }

        // Main state: Display the button to trigger opening the Plaid widget
        if (!plaid || !plaid.success) {
                return (
                        <Paper className={styles['button-container']} variant="outlined">
                                <Typography sx={{ fontSize: '0.8rem' }}>Click to securely log in to your bank account</Typography>
                                <Button
                                        variant="contained"
                                        color="primary"
                                        size="large"
                                        fullWidth
                                        onClick={() => setShowWidget(true)}
                                        disabled={showWidget}
                                        className={styles.button}
                                        loadingPosition="start"
                                        startIcon={
                                                showWidget ? (
                                                        <CircularProgress className={styles.loader} size="20px" />
                                                ) : (
                                                        <PlaidIcon className={styles.logo} />
                                                )
                                        }
                                >
                                        Bank Login
                                </Button>
                                <FormHelperText className={styles.error}>{plaidTouched ? plaidError : ''}</FormHelperText>
                                <PlaidWidget showWidget={showWidget} onWidget={handleWidget} />
                        </Paper>
                )
        }

	// Success state: Display the bank information
	return (
		<Paper variant="outlined" className={styles['confirm-container']}>
			<div className={styles.title}>Bank account</div>
			<Divider className={styles.divider} />
			<Paper variant="outlined" className={styles['confirm-inner']}>
				{plaid.logo ? (
					<img
						src={`data:image/png;base64,${plaid.logo}`}
						alt="Bank Logo"
						style={{ width: 50, height: 50 }}
					/>
				) : (
					<IconButton disabled={true} size="large">
						<AccountBalanceIcon />
					</IconButton>
				)}
				<div className={styles.spacer}>
					<div className={styles.title}>{plaid.institution}</div>
					<div>Account ending in {accountMask}</div>
				</div>
				<div className={styles['icon-container']}>
					<CheckCircleIcon className={styles['success-icon']} />
				</div>
			</Paper>
		</Paper>
	)
}

export default PlaidComponent
