import { useIsMobileViewport } from '@greenpay/hooks'
import { Plaid } from '@greenpay/models'
import { usePaymentDispatch, useSettingsSelect } from '@greenpay/redux'
import { useEffect, useRef } from '@wordpress/element'
import { dispatch } from '@wordpress/data'

interface PlaidWidgetProps {
	showWidget: boolean
	onWidget: (value: boolean) => void
}

const PlaidWidget: React.FC<PlaidWidgetProps> = ({ showWidget, onWidget }) => {
	const settings = useSettingsSelect().getSettings()
	const { setPlaid } = usePaymentDispatch()
	const isMobile = useIsMobileViewport()
	const iframeRef = useRef<HTMLIFrameElement | null>(null)
	const backdropRef = useRef<HTMLDivElement | null>(null)
	const uuid = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
    	? crypto.randomUUID()
    	: `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`

	// Set up message handler once
	useEffect(() => {
		const handler = (event: MessageEvent) => {
			try {
				const data = JSON.parse(event.data) as Plaid
				setPlaid(data)
				// Set method immediately when we have success + !isTAN so checkout has it even if
				// the effect in Plaid.tsx doesn't run (e.g. remount/timing).
				const raw = data as { success?: boolean | string; isTAN?: boolean | string }
				const success = raw.success === true || raw.success === 'true'
				const isTAN = raw.isTAN === true || raw.isTAN === 'true'
				if (success && !isTAN) {
					const paymentDispatch = dispatch('green-pay/payment') as {
						setMethod: (m: string) => void
						setAccountMask: (mask: string) => void
					}
					paymentDispatch.setMethod('plaid')
					paymentDispatch.setAccountMask(data.mask ?? '')
				}
				onWidget(false)
				if (backdropRef.current && document.body.contains(backdropRef.current)) {
					document.body.removeChild(backdropRef.current)
				}
				if (iframeRef.current && document.body.contains(iframeRef.current)) {
					document.body.removeChild(iframeRef.current)
				}
			} catch (e) {
				console.warn('Non-Plaid message received', e)
			}
		}
		window.addEventListener('message', handler)
		return () => window.removeEventListener('message', handler)
	}, [setPlaid, onWidget])

	// Add/remove iframe when showWidget changes
	useEffect(() => {
		if (!settings) return
		if (!showWidget) return

		const iframe = document.createElement('iframe')
		iframe.src = `${settings.endpoint}/Plaid/Woocommerce?client_id=${settings.clientId}&secret=${uuid}`
		iframe.title = 'Bank Login'
		iframe.style.position = 'fixed'
		iframe.style.border = 'none'
		iframe.style.zIndex = '99999'

		if (isMobile) {
			iframe.style.top = 'env(safe-area-inset-top, 0)'
			iframe.style.left = 'env(safe-area-inset-left, 0)'
			iframe.style.right = 'env(safe-area-inset-right, 0)'
			iframe.style.bottom = 'env(safe-area-inset-bottom, 0)'
			iframe.style.width = '100%'
			iframe.style.height = '100dvh'
		} else {
			const backdrop = document.createElement('div')
			backdrop.style.position = 'fixed'
			backdrop.style.inset = '0'
			backdrop.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
			backdrop.style.zIndex = '99998'
			document.body.appendChild(backdrop)
			backdropRef.current = backdrop

			iframe.style.top = '50%'
			iframe.style.left = '50%'
			iframe.style.transform = 'translate(-50%, -50%)'
			iframe.style.width = '100%'
			iframe.style.maxWidth = '480px'
			iframe.style.height = '80vh'
			iframe.style.maxHeight = '700px'
			iframe.style.borderRadius = '10px'
			iframe.style.boxShadow = '0 4px 24px rgba(0, 0, 0, 0.25)'
		}

		document.body.appendChild(iframe)
		iframeRef.current = iframe

		return () => {
			if (backdropRef.current && document.body.contains(backdropRef.current)) {
				document.body.removeChild(backdropRef.current)
				backdropRef.current = null
			}
			if (iframeRef.current && document.body.contains(iframeRef.current)) {
				document.body.removeChild(iframeRef.current)
				iframeRef.current = null
			}
		}
	}, [showWidget, isMobile, settings])

	return null // no longer render an inline iframe
}

export default PlaidWidget
