import { useCallback, useEffect, useRef, useState } from "react";
import { getApiCache } from "./storage";



interface UseSWCOPtions<T> {
    onError?: (e: unknown) => void;
    onLoad?: (data: T) => void;
    cacheOnly?: boolean;
    cacheTimeout?: number;
    // 自动开始加载
    autoStart?: boolean;
}
// 该hook用于在组件中通过key和异步action获取数据，并自动处理加载、错误和数据状态

export function useSWC<T, S extends any[] = any>(key: string, action: () => Promise<T>, options?: UseSWCOPtions<T>) {
    const optionsRef = useRef(options || {});
    optionsRef.current = options || {};
    const keyRef = useRef(key);
    const [data, setData] = useState<T | null | undefined>(() => getApiCache().getObject<T>(keyRef.current));
    const [loading, setLoading] = useState<true | 'background' | false>(true);
    const [error, setError] = useState<any>(null);

    const actionRef = useRef(action);
    actionRef.current = action;

    const dataRef = useRef(data);
    dataRef.current = data;
    const isMountedRef = useRef(true);
    const load = useCallback(async ()=> {
        setLoading(dataRef.current ? 'background' : true);
        setError(null);
         
        const options = optionsRef.current;
        const key = keyRef.current;
        try {
            const result = await actionRef.current();
            // @ts-ignore
            result && getApiCache().setObject(key, result, options.cacheTimeout || 86400 * 120);
            if (isMountedRef.current) {
                options?.onLoad?.(result);
                setData(result);
                setLoading(false);
            }
            
        } catch(err) {
            if (isMountedRef.current) {
                options?.onError?.(err);
                setError(err);
                setLoading(false);
            }
        }
    }, [])
    useEffect(() => {
        if (dataRef.current && optionsRef.current.cacheOnly) {

            setLoading(false);
            setError(null);
            return;
        }
        
        // @ts-ignore
        if ((optionsRef.current.autoStart !== false || optionsRef.current.autoStart)) {
            load();
        }
     
        return () => {
            isMountedRef.current = false;
        };
    }, []);

    const getOrLoad = useCallback(async ()=> {
        if (dataRef.current && optionsRef.current.cacheOnly) {
            setLoading(false);
            setError(null);
            return;
        }
        await load();
    }, [load]);

    return { data, loading, error, load: getOrLoad, refresh: load };
}

export const MAX_CACHE_TIME = 99999999999999;
