// import { Suspense } from '@univoq // Error - mismatch in imports version
import { JSX } from 'preact'
import { useSignal } from '@preact/signals'

function RenderError(
	{ error, fallback }: { error: Error; fallback: Fallback | undefined },
) {
	if (fallback) {
		return fallback({ error })
	}

	return (
		<output>
			<pre>{String(error)}</pre>
		</output>
	)
}

export type Fallback = ({ error }: { error: Error }) => JSX.Element

export type SuspenseProps = {
	loader: JSX.Element
	fallback?: Fallback
	signal?: AbortSignal
} & ({ children: Promise<JSX.Element> } | { value: Promise<JSX.Element> })

export default function Suspense(
	{ loader, fallback, signal, ...props }: SuspenseProps,
) {
	const displayed = useSignal(loader)
	let loaded = false

	signal?.addEventListener('abort', () => {
		if (loaded) return
		try {
			signal.throwIfAborted()
		} catch (error) {
			displayed.value = RenderError({ error, fallback })
		}
	})

	//Prevent transpilation error due to children expected to not be a promise
	const inner = 'value' in props ? props.value : props.children
	inner
		.then((element) => {
			if (signal?.aborted) return
			displayed.value = element
			loaded = true
		})
		.catch((error) => {
			if (signal?.aborted) return
			displayed.value = RenderError({ error, fallback })
		})

	return <>{displayed}</>
}
