import {
    createContext,
    type ReactNode,
    useContext,
    useEffect,
    useRef,
    useState,
} from 'react';

import {
    CloudOff,
    RefreshCcw,
} from 'lucide-react';

import { rpcCache } from '@/api/cache';
import type {
    CollectionRelationType,
    InitACPTType,
} from '@/api/types';
import {
    CollectionTableProps,
} from '@/components/CollectionTable/CollectionTable';
import {
    CollectionViewProps,
} from '@/components/CollectionView/CollectionView';
import { Button } from '@/components/ui/button';
import {
    Empty,
    EmptyContent,
    EmptyDescription,
    EmptyHeader,
    EmptyMedia,
    EmptyTitle,
} from '@/components/ui/empty';
import {
    MobileApp,
    MobileBlock,
    MobileButton,
    MobileLink,
    MobileNavbar,
    MobilePage,
} from '@/components/ui/mobile';
import { getClosestBrandColorClass } from '@/config';
import { Lang } from '@/lang/Lang';
import { EventEmitter } from '@/utils/event';

export type Theme = 'light' | 'dark' | 'system';

export interface AppConfig extends InitACPTType {
    color: string;
    isMobile: boolean;
    isDarkTheme: boolean;
    dialogStack: DialogStackItem[];
    openDialog: (props: CollectionViewProps) => void;
    closeDialog: (modalKey?: string) => void;
    initLoaded: boolean;
    focusDialogKey: string | undefined;
    hideTips: boolean;
    setHideTips: (hide: boolean) => void;
    toggleTheme: () => void;
    openTableDialog: (params: CollectionRelationType & { ids: string[] }) => void;

}

type DialogStackItem = {
    view?: CollectionViewProps
    table?: CollectionTableProps
}

const AppConfigContext = createContext<AppConfig | undefined>(undefined);

interface AppConfigProviderProps {
    children: ReactNode;
}


export function AppConfigProvider({
    children,
}: AppConfigProviderProps) {


    const [hideTips, setHideTips] = useState(false);

    const [isInternetError, setIsInternetError] = useState(false);

    useEffect(() => {

        EventEmitter.subscribe("internetError", () => {


            setIsInternetError(true);
        });



        const hideTips = localStorage.getItem('hideTips');
        if (hideTips === 'true') {
            setHideTips(true);
        }


        const theme = localStorage.getItem('_theme');
        if (theme === 'dark') {
            setIsDarkTheme(true);
        } else {
            setIsDarkTheme(false);
        }

    }, []);

    useEffect(() => {
        localStorage.setItem('hideTips', hideTips.toString());
    }, [hideTips]);


    const [isMobile, setIsMobile] = useState(false);
    const [data, setData] = useState<InitACPTType>({});

    const [initLoaded, setInitLoaded] = useState(false);

    const [isDarkTheme, setIsDarkTheme] = useState(false);


    const setTheme = (theme: 'light' | 'dark') => {
        const root = window.document.documentElement
        root.classList.remove("light", "dark")
        root.classList.add(theme);
    }

    const toggleTheme = () => {
        setIsDarkTheme(!isDarkTheme);

    }

    useEffect(() => {
        setTheme(isDarkTheme ? 'dark' : 'light');
        localStorage.setItem('_theme', isDarkTheme ? 'dark' : 'light');
    }, [isDarkTheme]);

    const initCalled = useRef(false);
    useEffect(() => {

        setIsMobile(window.innerWidth < 768);

        window.addEventListener('resize', () => {
            setIsMobile(window.innerWidth < 768);
        });

        if (initCalled.current) return;
        initCalled.current = true;
        rpcCache.init().then((data) => {
            if (data?.result) {
                setData(data.result ?? null);
                setInitLoaded(true);
            }
        });


    }, []);

    useEffect(() => {
        if (data.color) {
            document.documentElement.style.setProperty('--color-primary', data.color);
            document.documentElement.style.setProperty('--k-color-primary', data.color);

        }
    }, [data]);


    const [dialogStack, setDialogStack] = useState<DialogStackItem[]>([]);

    const [focusDialogKey, setFocusDialogKey] = useState<string | undefined>(undefined);

    useEffect(() => {

        if (dialogStack.length > 0) {

            let modalKey = undefined;
            if (dialogStack[dialogStack.length - 1].view) {
                modalKey = dialogStack?.[dialogStack.length - 1]?.view?.modalKey;
            } else if (dialogStack[dialogStack.length - 1].table) {
                modalKey = dialogStack?.[dialogStack.length - 1]?.table?.modalKey;
            }

            setFocusDialogKey(modalKey);
        } else {
            setFocusDialogKey(undefined);
        }

    }, [dialogStack]);

    const openDialog = (props: CollectionViewProps) => {



        setDialogStack((prev) => [...prev, {

            view: {
                ...props,
                modalKey: `collection_view_${props.collection}_${props._id ?? 'create'}_${props.clonedFrom ?? ''}`

            }
        }]);
    }

    const openTableDialog = (params: CollectionRelationType & { ids: string[] }) => {

        setDialogStack((prev) => [...prev, {
            table: {

                collection: params.collection!,
                defaultFilter: {
                    [params.key!]: {
                        in: params.ids,
                    }
                },

                modalKey: `collection_table_${params.collection}_${JSON.stringify(params.key) ?? ''}`
            }
        }]);
    }

    const closeDialog = (modalKey?: string) => {

        if (!modalKey) {
            return;
        }

        setDialogStack((prev) => prev.filter((item) => item.view?.modalKey !== modalKey && item.table?.modalKey !== modalKey));
    }

    const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);



    if (isInternetError) {

        return isMobile ? <MobileApp

            className={"k-color-brand-red"}

            theme={isIOS ? 'ios' : 'material'}
        >

            <MobilePage>

                <MobileNavbar
                    title={Lang.key("internet_error_navbar_title")}
                    right={<MobileLink
                        onClick={() => {
                            window.location.reload();
                        }}
                    >
                        <RefreshCcw className='mr-3' />
                    </MobileLink>}

                />
                <MobileBlock
                    outline
                    className='flex flex-col items-center justify-center'


                >
                    <div className='text-xl font-medium'>{Lang.key("internet_error_card_header")}</div>
                    <CloudOff
                        className='animate-pulse my-4'
                        size={60} />
                    <div

                    >{Lang.key("internet_error_card_description")}</div>

                </MobileBlock>
                <MobileBlock>
                    <MobileButton
                        onClick={() => {
                            window.location.reload();
                        }}
                    >
                        <RefreshCcw className='mr-3' />  {Lang.key("internet_error_card_button")}
                    </MobileButton>
                </MobileBlock>


            </MobilePage>

        </MobileApp> : <div className='w-screen h-screen flex items-center justify-center'>

            <Empty>
                <EmptyHeader>
                    <EmptyMedia variant="icon">
                        <CloudOff size={60} />
                    </EmptyMedia>
                    <EmptyTitle>{Lang.key("internet_error_card_header")}</EmptyTitle>
                    <EmptyDescription>{Lang.key("internet_error_card_description")}</EmptyDescription>
                </EmptyHeader>
                <EmptyContent>
                    <Button onClick={() => {
                        window.location.reload();
                    }}><RefreshCcw /> {Lang.key("internet_error_card_button")}</Button>
                </EmptyContent>
            </Empty>

        </div>


    }



    return (
        <AppConfigContext.Provider value={{ ...data, initLoaded, toggleTheme, focusDialogKey, color: data.color ?? '#000000', isMobile, isDarkTheme, openTableDialog, dialogStack, openDialog, closeDialog, hideTips, setHideTips }}>
            {isMobile ? <MobileApp

                className={getClosestBrandColorClass(data.color)}

                theme={isIOS ? 'ios' : 'material'}
            >{children}</MobileApp> : children}
        </AppConfigContext.Provider>
    );
}

export function useAppConfig(): AppConfig {
    const context = useContext(AppConfigContext);
    if (context === undefined) {
        throw new Error('useAppConfig must be used within an AppConfigProvider');
    }
    return context;
}

