"use client";

import React, { useEffect, useMemo } from "react";
import { CenteredView, Typography } from "@firecms/ui";
import { AuthController } from "../types";
import { CustomizationController, FireCMSContext, FireCMSPlugin, FireCMSProps, User } from "../types";
import { AuthControllerContext, ModeControllerProvider } from "../contexts";
import { useBuildSideEntityController } from "../internal/useBuildSideEntityController";
import { useCustomizationController, useFireCMSContext, useTranslation, ModeController } from "../hooks";
import { useBuildModeController } from "../hooks/useBuildModeController";
import { useBuildSideDialogsController } from "../internal/useBuildSideDialogsController";
import { ErrorView } from "../components";
import { StorageSourceContext } from "../contexts/StorageSourceContext";
import { UserConfigurationPersistenceContext } from "../contexts/UserConfigurationPersistenceContext";
import { DataSourceContext } from "../contexts/DataSourceContext";
import { SideEntityControllerContext } from "../contexts/SideEntityControllerContext";
import { NavigationContext } from "../contexts/NavigationContext";
import { SideDialogsControllerContext } from "../contexts/SideDialogsControllerContext";
import { DialogsProvider } from "../contexts/DialogsProvider";
import { useBuildDataSource } from "../internal/useBuildDataSource";
import { CustomizationControllerContext } from "../contexts/CustomizationControllerContext";
import { AnalyticsContext } from "../contexts/AnalyticsContext";
import { useProjectLog } from "../hooks/useProjectLog";
import { BreadcrumbsProvider } from "../contexts/BreacrumbsContext";
import { InternalUserManagementContext } from "../contexts/InternalUserManagementContext";

/**
 * If you are using independent components of the CMS
 * you need to wrap them with this main component, so the internal hooks work.
 *
 * This is the main component of FireCMS. It acts as the provider of all the
 * internal contexts and hooks.
 *
 * You only need to use this component if you are building a custom app.
 *
 * @group Core
 */
export function FireCMS<USER extends User>(props: FireCMSProps<USER>) {

    const {
        children,
        entityLinkBuilder,
        userConfigPersistence,
        dateTimeFormat,
        locale,
        authController,
        storageSource,
        dataSourceDelegate,
        plugins: _pluginsProp,
        onAnalyticsEvent,
        propertyConfigs,
        entityViews,
        entityActions,
        components,
        navigationController,
        apiKey,
        userManagement: _userManagement
    } = props;

    if (_pluginsProp) {
        console.warn("The `plugins` prop is deprecated in the FireCMS component. You should pass your plugins to `useBuildNavigationController` instead.");
    }

    const { t, i18n } = useTranslation();

    const modeController = useBuildModeController();

    const plugins = navigationController.plugins ?? _pluginsProp;
    const userManagement = plugins?.find(p => p.userManagement)?.userManagement
        ?? _userManagement
        ?? {
            users: [],
            getUser: (uid: string) => null
        };

    const sideDialogsController = useBuildSideDialogsController();
    const sideEntityController = useBuildSideEntityController(navigationController, sideDialogsController, authController);

    const pluginsLoading = plugins?.some(p => p.loading) ?? false;

    const loading = authController.initialLoading || navigationController.loading || pluginsLoading;

    const customizationController: CustomizationController = {
        dateTimeFormat,
        locale,
        entityLinkBuilder,
        plugins,
        entityViews: entityViews ?? [],
        entityActions: entityActions ?? [],
        propertyConfigs: propertyConfigs ?? {},
        components
    };

    const analyticsController = useMemo(() => ({
        onAnalyticsEvent
    }), []);

    const accessResponse = useProjectLog({
        apiKey,
        authController,
        dataSourceDelegate,
        plugins
    });

    /**
     * Controller in charge of fetching and persisting data
     */
    const dataSource = useBuildDataSource({
        delegate: dataSourceDelegate,
        propertyConfigs,
        navigationController,
        authController
    });

    // Inject plugin translations into the existing i18next instance
    useEffect(() => {
        if (!i18n) return;
        plugins?.forEach(plugin => {
            if (plugin.i18n) {
                Object.keys(plugin.i18n).forEach(locale => {
                    i18n.addResourceBundle(
                        locale,
                        "firecms_core",
                        plugin.i18n![locale],
                        true,  // deep merge
                        true   // overwrite
                    );
                });
            }
        });
    }, [i18n, plugins]);

    if (accessResponse?.message) {
        console.warn(accessResponse.message);
    }

    if (navigationController.navigationLoadingError) {
        return (
            <CenteredView maxWidth={"md"}>
                <ErrorView
                    title={"Error loading navigation"}
                    error={navigationController.navigationLoadingError}/>
            </CenteredView>
        );
    }

    if (authController.authError) {
        return (
            <CenteredView maxWidth={"md"}>
                <ErrorView
                    title={"Error loading auth"}
                    error={authController.authError}/>
            </CenteredView>
        );
    }

    if (accessResponse?.blocked) {
        return (
            <CenteredView maxWidth={"md"} fullScreen={true} className={"flex flex-col gap-2"}>
                {/* eslint-disable-next-line i18next/no-literal-string */}
                <Typography variant={"h4"} gutterBottom>
                    {t("license_needed")}
                </Typography>
                <Typography>
                    {(() => {
                        const parts = t("license_description", { email: "%%EMAIL%%" }).split("%%EMAIL%%");
                        return <>{parts[0]}<a href={"mailto:hello@firecms.co"}>hello@firecms.co</a>{parts[1]}</>;
                    })()}
                </Typography>
                {accessResponse?.message &&
                    <Typography>{accessResponse?.message}</Typography>}
            </CenteredView>
        );
    }

    return (
        <AnalyticsContext.Provider value={analyticsController}>
            <CustomizationControllerContext.Provider value={customizationController}>
                <UserConfigurationPersistenceContext.Provider
                    value={userConfigPersistence}>
                    <StorageSourceContext.Provider
                        value={storageSource}>
                        <DataSourceContext.Provider
                            value={dataSource}>
                            <AuthControllerContext.Provider
                                value={authController}>
                                <SideDialogsControllerContext.Provider
                                    value={sideDialogsController}>
                                    <SideEntityControllerContext.Provider
                                        value={sideEntityController}>
                                        <NavigationContext.Provider
                                            value={navigationController}>
                                            <InternalUserManagementContext.Provider value={userManagement}>
                                                <DialogsProvider>
                                                    <BreadcrumbsProvider>
                                                        <FireCMSInternal
                                                            loading={loading}>
                                                            {children}
                                                        </FireCMSInternal>
                                                    </BreadcrumbsProvider>
                                                </DialogsProvider>
                                            </InternalUserManagementContext.Provider>
                                        </NavigationContext.Provider>
                                    </SideEntityControllerContext.Provider>
                                </SideDialogsControllerContext.Provider>
                            </AuthControllerContext.Provider>
                        </DataSourceContext.Provider>
                    </StorageSourceContext.Provider>
                </UserConfigurationPersistenceContext.Provider>
            </CustomizationControllerContext.Provider>
        </AnalyticsContext.Provider>
    );

}

function FireCMSInternal({
                             loading,
                             children
                         }: {
    loading: boolean;
    children: (props: {
        context: FireCMSContext;
        loading: boolean;
    }) => React.ReactNode;
}) {

    const context = useFireCMSContext();
    const customizationController = useCustomizationController();

    let childrenResult = children({
        context,
        loading
    });

    const plugins = customizationController.plugins;
    if (!loading && plugins) {
        plugins.forEach((plugin: FireCMSPlugin) => {
            if (plugin.provider) {
                childrenResult = (
                    <plugin.provider.Component {...plugin.provider.props}
                                               context={context}>
                        {childrenResult}
                    </plugin.provider.Component>
                );
            }
        });
    }

    return <>{childrenResult}</>;
}
