import { useState, useEffect, useCallback, useRef, createElement } from 'react';
import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native';
const asyncChunkMap = new Map();
const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 20,
        backgroundColor: '#fff'
    },
    loadingImage: {
        width: 100,
        height: 100,
        marginTop: 220,
        alignSelf: 'center'
    },
    buttonText: {
        color: '#fff',
        fontSize: 16,
        fontWeight: '500',
        textAlign: 'center'
    },
    errorImage: {
        marginTop: 80,
        width: 220,
        aspectRatio: 1,
        alignSelf: 'center'
    },
    errorText: {
        fontSize: 16,
        textAlign: 'center',
        color: '#333',
        marginBottom: 20
    },
    retryButton: {
        position: 'absolute',
        bottom: 54,
        left: 20,
        right: 20,
        backgroundColor: '#fff',
        paddingVertical: 15,
        borderRadius: 30,
        marginTop: 40,
        borderWidth: 1,
        borderColor: '#FF5F00'
    },
    retryButtonText: {
        color: '#FF5F00',
        fontSize: 16,
        fontWeight: '500',
        textAlign: 'center'
    }
});
const DefaultFallback = ({ onReload }) => {
    return (<View style={styles.container}>
      <Image source={{
            uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
        }} style={styles.errorImage} resizeMode="contain"/>
      <Text style={styles.errorText}>网络出了点问题，请查看网络环境</Text>
      <TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
        <Text style={styles.retryButtonText}>点击重试</Text>
      </TouchableOpacity>
    </View>);
};
const DefaultLoading = () => {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const FastImageModule = require('@d11/react-native-fast-image');
    const FastImage = FastImageModule.default || FastImageModule;
    return (<View style={styles.container}>
      <FastImage style={styles.loadingImage} source={{
            uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
        }} resizeMode={FastImage.resizeMode.contain}></FastImage>
    </View>);
};
const AsyncSuspense = ({ type, chunkName, moduleId, innerProps, getLoading, getFallback, getChildren }) => {
    const [status, setStatus] = useState('pending');
    const chunkLoaded = asyncChunkMap.has(moduleId);
    const loadChunkPromise = useRef(null);
    const reloadPage = useCallback(() => {
        setStatus('pending');
    }, []);
    useEffect(() => {
        let cancelled = false;
        if (!chunkLoaded && status === 'pending') {
            if (loadChunkPromise.current) {
                loadChunkPromise
                    .current.then((res) => {
                    if (cancelled)
                        return;
                    asyncChunkMap.set(moduleId, res);
                    setStatus('loaded');
                })
                    .catch((e) => {
                    if (cancelled)
                        return;
                    if (type === 'component') {
                        global.__mpxAppCbs.lazyLoad.forEach((cb) => {
                            // eslint-disable-next-line node/no-callback-literal
                            cb({
                                type: 'subpackage',
                                subpackage: [chunkName],
                                errMsg: `loadSubpackage: ${e.type}`
                            });
                        });
                    }
                    if (type === 'page' && typeof mpxGlobal.__mpx.config?.rnConfig?.onLazyLoadPageError === 'function') {
                        mpxGlobal.__mpx.config.rnConfig.onLazyLoadPageError({
                            subpackage: chunkName,
                            errType: e.type
                        });
                    }
                    loadChunkPromise.current = null;
                    setStatus('error');
                });
            }
        }
        return () => {
            cancelled = true;
        };
    }, [status]);
    if (chunkLoaded) {
        const Comp = asyncChunkMap.get(moduleId);
        return createElement(Comp, innerProps);
    }
    else if (status === 'error') {
        if (type === 'page') {
            const fallback = getFallback ? getFallback() : DefaultFallback;
            return createElement(fallback, { onReload: reloadPage });
        }
        else {
            return getFallback ? createElement(getFallback(), innerProps) : null;
        }
    }
    else {
        if (!loadChunkPromise.current) {
            loadChunkPromise.current = getChildren();
        }
        if (type === 'page') {
            const loading = getLoading ? getLoading() : DefaultLoading;
            return createElement(loading);
        }
        else {
            return getFallback ? createElement(getFallback(), innerProps) : null;
        }
    }
};
AsyncSuspense.displayName = 'MpxAsyncSuspense';
export default AsyncSuspense;
