import { Badge, Spin } from "antd";
import { observer } from "mobx-react";
import { Suspense, lazy, useCallback, useLayoutEffect, useMemo, useState } from "react";
import { NavLink, Outlet, Route, RouterProvider, createHashRouter, createRoutesFromElements } from "react-router-dom";

import { Notices, useI18nProvider, useUpsellProvider } from "@devowl-wp/react-cookie-banner-admin";
import { JOB_DONE_EVENT_PREFIX } from "@devowl-wp/real-queue";
import { SuspenseChunkTranslation } from "@devowl-wp/utils";

import { BlockerLayout } from "./config/blocker/layout.js";
import { ConfigFooter } from "./config/footer.js";
import { ConfigHeader } from "./config/header.js";
import { NoticeAnonymousScriptNotWritable } from "./config/noticeAnonymousScriptNotWritable.js";
import { NoticeBannerActiveNoCookies } from "./config/noticeBannerActiveNoCookies.js";
import { NoticeBannerlessConsent } from "./config/noticeBannerlessConsent.js";
import { NoticeNoManager } from "./config/noticeNoManager.js";
import { NoticeRevisionNeedsRetrigger } from "./config/noticeRevisionNeedsRetrigger.js";
import { NoticeServiceDataProcessingInUnsafeCountries } from "./config/noticeServiceDataProcessingInUnsafeCountries.js";
import { RouterScrollToTop } from "./routerScrollToTop.js";
import { useScannerProgress } from "../hooks/useScannerProgress.js";
import { useStores } from "../store/stores.js";
import { AUTOMATIC_SCAN_STATER_QUEUE_JOB } from "../types/queue.js";
import { __, _i, _n, _x } from "../utils/i18n.js";
import { ConsentDbConsentMigrationV2Badge } from "./config/consent/dbConsentMigrationV2Badge.js";

import type { CSSProperties, ComponentProps, FC, ReactNode } from "react";

const CSS_SPINNER_IN_CONTENT: CSSProperties = { display: "block", marginTop: 10 };

// Lazy load components
const createSuspenseComponent = (tab: string, children: ReactNode) => ({
    Component: () => (
        <SuspenseChunkTranslation
            chunkFile={__webpack_get_script_filename__(`chunk-config-tab-${tab}`)}
            options={() => useStores().optionStore}
            fallback={<Spin spinning style={CSS_SPINNER_IN_CONTENT} />}
        >
            {children}
        </SuspenseChunkTranslation>
    ),
});

const DashboardCards = () =>
    import(/* webpackChunkName: "chunk-config-tab-dashboard" */ "./config/dashboard/cards.js").then(
        ({ DashboardCards }) => createSuspenseComponent("dashboard", <DashboardCards />),
    );

const SettingsForm = () =>
    import(/* webpackChunkName: "chunk-config-tab-settings" */ "./config/settings/form.js").then(({ SettingsForm }) =>
        createSuspenseComponent("settings", <SettingsForm />),
    );

const ScannerList = () =>
    import(/* webpackChunkName: "chunk-config-tab-scanner" */ "./config/scanner/list.js").then(({ ScannerList }) =>
        createSuspenseComponent("scanner", <ScannerList />),
    );

const CookieGroupsTabLayout = () =>
    import(/* webpackChunkName: "chunk-config-tab-cookies" */ "./config/cookies/groups/layout.js").then(
        ({ CookieGroupsTabLayout }) => createSuspenseComponent("cookies", <CookieGroupsTabLayout />),
    );

const CookiesList = () =>
    import(/* webpackChunkName: "chunk-config-tab-cookies" */ "./config/cookies/list.js").then(({ CookiesList }) =>
        createSuspenseComponent("cookies", <CookiesList />),
    );

const CookieTemplateCenter = () =>
    import(/* webpackChunkName: "chunk-config-tab-cookies" */ "./config/cookies/templateCenter.js").then(
        ({ CookieTemplateCenter }) => createSuspenseComponent("cookies", <CookieTemplateCenter />),
    );

const CookieEditForm = () =>
    import(/* webpackChunkName: "chunk-config-tab-cookies" */ "./config/cookies/form.js").then(({ CookieEditForm }) =>
        createSuspenseComponent("cookies", <CookieEditForm />),
    );

const TcfLayout = () =>
    import(/* webpackChunkName: "chunk-config-tab-tcf" */ "./config/cookies/tcf/layout.js").then(({ TcfLayout }) =>
        createSuspenseComponent("tcf", <TcfLayout />),
    );

const TcfVendorConfigurationList = () =>
    import(/* webpackChunkName: "chunk-config-tab-tcf" */ "./config/cookies/tcf/list.js").then(
        ({ TcfVendorConfigurationList }) => createSuspenseComponent("tcf", <TcfVendorConfigurationList />),
    );

const TcfVendorSelector = () =>
    import(/* webpackChunkName: "chunk-config-tab-tcf" */ "./config/cookies/tcf/vendorSelector.js").then(
        ({ TcfVendorSelector }) => createSuspenseComponent("tcf", <TcfVendorSelector />),
    );

const TcfVendorConfigurationForm = () =>
    import(/* webpackChunkName: "chunk-config-tab-tcf" */ "./config/cookies/tcf/form.js").then(
        ({ TcfVendorConfigurationForm }) => createSuspenseComponent("tcf", <TcfVendorConfigurationForm />),
    );

const ConsentTabRouter = () =>
    import(/* webpackChunkName: "chunk-config-tab-consent" */ "./config/consent/tabRouter.js").then(
        ({ ConsentTabRouter }) => createSuspenseComponent("consent", <ConsentTabRouter />),
    );

const BlockerList = () =>
    import(/* webpackChunkName: "chunk-config-tab-blocker" */ "./config/blocker/list.js").then(({ BlockerList }) =>
        createSuspenseComponent("blocker", <BlockerList />),
    );

const BlockerTemplateCenter = () =>
    import(/* webpackChunkName: "chunk-config-tab-blocker" */ "./config/blocker/templateCenter.js").then(
        ({ BlockerTemplateCenter }) => createSuspenseComponent("blocker", <BlockerTemplateCenter />),
    );

const BlockerEditForm = () =>
    import(/* webpackChunkName: "chunk-config-tab-blocker" */ "./config/blocker/form.js").then(({ BlockerEditForm }) =>
        createSuspenseComponent("blocker", <BlockerEditForm />),
    );

const ImportExportCards = () =>
    import(/* webpackChunkName: "chunk-config-tab-import" */ "./config/import/cards.js").then(({ ImportExportCards }) =>
        createSuspenseComponent("import", <ImportExportCards />),
    );

const ConfigLicensing = () =>
    import(/* webpackChunkName: "chunk-config-tab-licensing" */ "./config/licensing/licensing.js").then(
        ({ ConfigLicensing }) => createSuspenseComponent("licensing", <ConfigLicensing />),
    );

const ConfigLicensingReactLazy = lazy(() => ConfigLicensing().then(({ Component }) => ({ default: Component })));

const ConfigApp: FC = () => {
    const router = useMemo(
        () =>
            createHashRouter(
                createRoutesFromElements(
                    <Route element={<ConfigAppLayout />}>
                        <Route index lazy={DashboardCards} />
                        <Route path="settings/:tab?" lazy={SettingsForm} />
                        <Route path="scanner" lazy={ScannerList} />
                        <Route path="cookies" lazy={CookieGroupsTabLayout}>
                            <Route path="tcf-vendors" lazy={TcfLayout}>
                                <Route index lazy={TcfVendorConfigurationList} />
                                <Route path="new" lazy={TcfVendorSelector} />
                                <Route path="edit/:vendorConfiguration" lazy={TcfVendorConfigurationForm} />
                            </Route>
                            <Route path=":cookieGroup?" lazy={CookiesList} />
                            <Route path=":cookieGroup/new" lazy={CookieTemplateCenter} />
                            <Route path=":cookieGroup/edit/:cookie" lazy={CookieEditForm} />
                        </Route>
                        <Route path="consent/:tab?" lazy={ConsentTabRouter} />
                        <Route path="blocker" element={<BlockerLayout />}>
                            <Route index lazy={BlockerList} />
                            <Route path="new" lazy={BlockerTemplateCenter} />
                            <Route path="edit/:blocker" lazy={BlockerEditForm} />
                        </Route>
                        <Route path="import" lazy={ImportExportCards} />
                        <Route path="licensing" lazy={ConfigLicensing} />
                    </Route>,
                ),
            ),
        [],
    );

    return <RouterProvider router={router} />;
};

const ConfigAppLayout: FC = observer(() => {
    const { percent: scanPercent, remaining: scanRemaining, currentJob } = useScannerProgress();
    const { optionStore, checklistStore } = useStores();
    const {
        others: {
            isPro,
            isLicensed,
            proUrl,
            hints,
            showLicenseFormImmediate,
            colorScheme: [, , badgeColor],
            isDemoEnv,
            capabilities: { activate_plugins },
        },
        fomoCoupon,
        checkSavingConsentViaRestApiEndpointWorkingHtml,
        templateUpdateNoticeHtml,
        templateSuccessorsNoticeHtml,
        googleConsentModeNoticesHtml,
        servicesWithEmptyPrivacyPolicyNoticeHtml,
    } = optionStore;
    const [isReady, setIsReady] = useState(false);

    // Initially fetch settings here so the form is shown
    useLayoutEffect(() => {
        optionStore.fetchSettings().then(() => {
            setIsReady(true);
        });

        // Listen to the automatic scan starter and update the checklist
        const listener = (/*_: CustomEvent<JobDoneEvent>*/) => {
            checklistStore.fetchChecklist();
        };

        const event = `${JOB_DONE_EVENT_PREFIX}${AUTOMATIC_SCAN_STATER_QUEUE_JOB}`;
        document.addEventListener(event, listener as any);
        return () => {
            document.removeEventListener(event, listener as any);
        };
    }, []);

    const [I18nContextProvider, i18nContextValue] = useI18nProvider({ __, _i, _n, _x });
    const [UpsellContextProvider, upsellContextValue] = useUpsellProvider(
        {
            fomoCoupon,
            isPro,
            isLicensed,
            isDemoEnv,
            proUrl,
            hint: hints?.proDialog,
        },
        {},
        {
            inherit: ["isLicensed", "fomoCoupon"],
        },
    );

    const navLinkClassName: Extract<ComponentProps<typeof NavLink>["className"], (...args: any[]) => any> = useCallback(
        ({ isActive }) => (isActive ? "nav-tab nav-tab-active" : "nav-tab"),
        [],
    );

    return (
        <I18nContextProvider value={i18nContextValue}>
            <UpsellContextProvider value={upsellContextValue}>
                {showLicenseFormImmediate ? (
                    <Suspense fallback={<Spin spinning style={CSS_SPINNER_IN_CONTENT} />}>
                        <ConfigLicensingReactLazy />
                    </Suspense>
                ) : (
                    <Spin spinning={!isReady}>
                        <ConfigHeader />
                        <nav className="nav-tab-wrapper wp-clearfix">
                            <NavLink to="/" className={navLinkClassName} end>
                                {__("Dashboard")}
                            </NavLink>
                            <NavLink to="/settings" className={navLinkClassName}>
                                {__("Settings")}
                            </NavLink>
                            <NavLink to="/scanner" className={navLinkClassName}>
                                {scanRemaining > 0 && scanPercent > 0 && currentJob?.group_position > 0 ? (
                                    <Badge
                                        count={`${scanPercent} %`}
                                        style={{
                                            top: -11,
                                            fontSize: 10,
                                            height: 16,
                                            lineHeight: "16px",
                                            background: badgeColor,
                                        }}
                                    >
                                        {__("Scanner")}
                                    </Badge>
                                ) : (
                                    __("Scanner")
                                )}
                            </NavLink>
                            <NavLink to="/cookies" className={navLinkClassName}>
                                {__("Services (Cookies)")}
                            </NavLink>
                            <NavLink to="/blocker" className={navLinkClassName}>
                                {__("Content Blocker")}
                            </NavLink>
                            <NavLink to="/consent" className={navLinkClassName}>
                                <ConsentDbConsentMigrationV2Badge>{__("Consent")}</ConsentDbConsentMigrationV2Badge>
                            </NavLink>
                            <NavLink to="/import" className={navLinkClassName}>
                                {__("Import / Export")}
                            </NavLink>
                            {window.location.host !== "try.devowl.io" && activate_plugins && (
                                <NavLink to="/licensing" className={navLinkClassName}>
                                    {__("Licensing")}
                                </NavLink>
                            )}
                            <a
                                href={__("https://devowl.io/support/")}
                                className="nav-tab"
                                target="_blank"
                                rel="noreferrer"
                            >
                                {__("Support")}
                            </a>
                        </nav>
                        <NoticeRevisionNeedsRetrigger />
                        <NoticeServiceDataProcessingInUnsafeCountries />
                        <Notices
                            notices={[
                                { severity: "error", message: checkSavingConsentViaRestApiEndpointWorkingHtml },
                                { severity: "warning", message: servicesWithEmptyPrivacyPolicyNoticeHtml },
                                { severity: "warning", message: templateUpdateNoticeHtml },
                                { severity: "warning", message: templateSuccessorsNoticeHtml },
                                ...googleConsentModeNoticesHtml.map((s) => ({
                                    severity: "warning" as const,
                                    message: s,
                                })),
                            ]}
                        />
                        <NoticeBannerActiveNoCookies />
                        <NoticeAnonymousScriptNotWritable />
                        <NoticeNoManager />
                        <NoticeBannerlessConsent />
                        <RouterScrollToTop />
                        <Suspense fallback={<Spin spinning style={CSS_SPINNER_IN_CONTENT} />}>
                            {isReady && <Outlet />}
                        </Suspense>
                        <ConfigFooter />
                    </Spin>
                )}
            </UpsellContextProvider>
        </I18nContextProvider>
    );
});

export { ConfigApp, ConfigAppLayout, createSuspenseComponent, CSS_SPINNER_IN_CONTENT };
