// react
import React, { ComponentType, useEffect, useMemo } from "react";
// third-party
import AppBase, { AppContext, AppProps } from "next/app";
import Head from "next/head";
import { useRouter } from "next/router";
import { NextComponentType, NextPageContext } from "next";
import { Provider } from "react-redux";
import { Store } from "redux";
// application
import config from "~/config";
import LanguageProvider, { getLanguageInitialProps, ILanguageProviderProps } from "~/services/i18n/provider";
import Layout from "~/components/Layout";
import PageTitle from "~/components/shared/PageTitle";
import { AppDispatch } from "~/store/types";
import { CurrentVehicleGarageProvider } from "~/services/current-vehicle";
import { getLanguageByLocale } from "~/services/i18n/utils";
import { load, save, wrapper } from "~/store/store";
import { optionsSetAll } from "~/store/options/optionsActions";
import { useApplyClientState } from "~/store/client";
import { useLoadUserVehicles } from "~/store/garage/garageHooks";
import { MobileMenuProvider } from "~/services/mobileMenuContext";
// styles
import "../scss/index.scss";
// import '../scss/style.header-spaceship-variant-one.scss';
import "../scss/style.header-spaceship-variant-two.scss";
// import '../scss/style.header-spaceship-variant-three.scss';
// import '../scss/style.header-classic-variant-one.scss';
import "../scss/style.header-classic-variant-two.scss";
// import '../scss/style.header-classic-variant-three.scss';
// import '../scss/style.header-classic-variant-four.scss';
// import '../scss/style.header-classic-variant-five.scss';
// import '../scss/style.mobile-header-variant-one.scss';
import "../scss/style.mobile-header-variant-two.scss";
import "@fortawesome/fontawesome-free/css/all.min.css";
/* ===== MONOLITO (admin merged from apps/admin) ===== */
import { AuthProvider } from "~/admin/contexts/AuthContext";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import "~/admin/scss/index.scss";

interface Props extends AppProps {
    languageInitialProps: ILanguageProviderProps;
    Component: NextComponentType<NextPageContext, any> & {
        Layout: ComponentType;
    };
}

function AppSetup({ store }: { store: Store }) {
    const applyClientState = useApplyClientState();
    const loadUserVehicles = useLoadUserVehicles();

    // Loading and saving state on the client side (cart, wishlist, etc.).
    useEffect(() => {
        const state = load();

        applyClientState(state || {});

        if (process.browser) {
            store.subscribe(() => {
                save(store.getState());
            });
        }
    }, [store, applyClientState]);

    // Load user vehicles
    useEffect(() => {
        loadUserVehicles().then();
    }, [loadUserVehicles]);

    return null;
}

function App({ Component, pageProps, languageInitialProps }: Props & { [key: string]: any }) {
    const { store, props: wrappedProps } = wrapper.useWrappedStore(
        useMemo(
            () => ({
                ...pageProps,
                languageInitialProps,
                Component,
            }),
            [Component, pageProps, languageInitialProps]
        )
    );
    const router = useRouter();

    // Scroll to top on route change (but not on page pagination)
    useEffect(() => {
        let lastPathname = router.pathname;
        let lastPage = router.query.page;

        const scrollToTop = () => {
            window.scrollTo({ top: 0, left: 0, behavior: "auto" });
            document.documentElement.scrollTop = 0;
            document.body.scrollTop = 0;
        };

        const handleRouteChangeStart = () => {
            lastPathname = router.pathname;
            lastPage = router.query.page;
        };

        const handleRouteChangeComplete = (url: string) => {
            // No scroll to top if only the page query param changed
            const urlObj = new URL(url, window.location.origin);
            const newPathname = urlObj.pathname;
            const newPage = urlObj.searchParams.get('page');
            if (newPathname === lastPathname && newPage !== lastPage) {
                return; // only page changed, don't scroll to top
            }
            scrollToTop();
            setTimeout(scrollToTop, 50);
            setTimeout(scrollToTop, 150);
        };

        router.events.on("routeChangeStart", handleRouteChangeStart);
        router.events.on("routeChangeComplete", handleRouteChangeComplete);
        return () => {
            router.events.off("routeChangeStart", handleRouteChangeStart);
            router.events.off("routeChangeComplete", handleRouteChangeComplete);
        };
    }, [router]);

    const page = useMemo(() => {
        const PageLayout = Component.Layout || React.Fragment;

        // El panel admin (y su login) es pantalla completa: NO debe envolverse
        // en el header/footer del catálogo.
        const isAdminArea = router.pathname.startsWith("/admin");

        if (isAdminArea) {
            return <Component {...pageProps} />;
        }

        return (
            <Layout>
                <PageLayout>
                    <Component {...pageProps} />
                </PageLayout>
            </Layout>
        );
    }, [Component, pageProps, router.pathname]);

    // noinspection HtmlRequiredTitleElement
    return (
        <Provider store={store}>
            <AppSetup store={store} />
                <LanguageProvider {...languageInitialProps}>
            <AuthProvider>
                <CurrentVehicleGarageProvider>
                    <MobileMenuProvider>
                        <PageTitle />

                <Head>
                    <meta name="viewport" content="width=device-width, initial-scale=1" />
                    <meta name="description" content="" />
                    <meta name="keywords" content="" />
                    <meta name="author" content="" />
                    <meta name="robots" content="index, follow" />
                    <meta name="googlebot" content="index, follow" />
                    <link rel="canonical" href="" />
                    <link rel="shortcut icon" href="" />
                    <link rel="apple-touch-icon" href="" />
                    <link rel="apple-touch-icon-precomposed" href="" />
                    <link rel="icon" href="/images/favicon.ico" />
                    <link
                        rel="stylesheet"
                        href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css"
                    />
                </Head>

                <div className="page-reveal">
                    {page}
                </div>
                <ToastContainer
                    position="top-right"
                    autoClose={3000}
                    hideProgressBar={false}
                    newestOnTop
                    closeOnClick
                    rtl={false}
                    pauseOnFocusLoss={false}
                    draggable
                    pauseOnHover
                    limit={3}
                />
                    </MobileMenuProvider>
                </CurrentVehicleGarageProvider>
            </AuthProvider>
        </LanguageProvider>
        </Provider>
    );
}

App.getInitialProps = wrapper.getInitialAppProps((store) => async (context: AppContext) => {
    const dispatch = store.dispatch as AppDispatch;

    await dispatch(
        optionsSetAll({
            desktopHeaderVariant: config.desktopHeaderVariant,
            mobileHeaderVariant: config.mobileHeaderVariant,
        })
    );

    const language = getLanguageByLocale(context.router.locale!);

    return {
        ...(await AppBase.getInitialProps(context)),
        languageInitialProps: await getLanguageInitialProps(language),
    };
});

// noinspection JSUnusedGlobalSymbols
export default App;
