import "./style.scss";

import { useMediaQuery } from "@mui/material";
import CssBaseline from "@mui/material/CssBaseline";
import { styled, ThemeProvider } from "@mui/material/styles";
import { lazy, Suspense, useCallback, useEffect, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import { Navigate, Route, Routes, useLocation } from "react-router-dom";
import { useAccount, useConnect, useChainId, useConfig, usePublicClient, injected } from "wagmi";

import Messages from "./components/Messages/Messages";
import NavDrawer from "./components/Sidebar/NavDrawer";
import Sidebar from "./components/Sidebar/Sidebar";
import TopBar from "./components/TopBar/TopBar";

import { shouldTriggerSafetyCheck } from "./helpers";
import { isNetworkAvailable } from "./constants";
import useTheme from "./hooks/useTheme";
import { dark as darkTheme } from "./themes/dark.js";
import { girth as gTheme } from "./themes/girth.js";
import { light as lightTheme } from "./themes/light.js";

// Dynamic Imports for code splitting
const Bonds = lazy(() => import("./containers/Bond/Bonds"));
const BondModalContainer = lazy(() => import("./containers/Bond/BondModal"));
const StakeContainer = lazy(() => import("./containers/Stake/StakeContainer"));
const TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard"));
const Faucet = lazy(() => import("./containers/Faucet/Faucet"));
const Dex = lazy(() => import("./containers/Dex/Dex"));
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));

const PREFIX = "App";

const classes = {
    drawer: `${PREFIX}-drawer`,
    content: `${PREFIX}-content`,
    contentShift: `${PREFIX}-contentShift`,
    toolbar: `${PREFIX}-toolbar`,
    drawerPaper: `${PREFIX}-drawerPaper`,
    notification: `${PREFIX}-notification`,
};

const StyledDiv = styled("div")(({ theme }) => ({
    [`& .${classes.drawer}`]: {
        [theme.breakpoints.up("md")]: {
            width: drawerWidth,
            flexShrink: 0,
        },
    },

    [`& .${classes.content}`]: {
        flexGrow: 1,
        padding: "15px",
        transition: theme.transitions.create("margin", {
            easing: theme.transitions.easing.sharp,
            duration: transitionDuration,
        }),
        marginLeft: drawerWidth,
        marginTop: "-48.5px",
    },

    [`& .${classes.contentShift}`]: {
        transition: theme.transitions.create("margin", {
            easing: theme.transitions.easing.easeOut,
            duration: transitionDuration,
        }),
        marginLeft: 0,
    },

    // necessary for content to be below app bar
    [`& .${classes.toolbar}`]: theme.mixins.toolbar,

    [`& .${classes.drawerPaper}`]: {
        width: drawerWidth,
    },

    [`& .${classes.notification}`]: {
        marginLeft: "264px",
    },
}));

// 😬 Sorry for all the console logging
const DEBUG = false;

// 🛰 providers
if (DEBUG) console.log("📡 Connecting to Mainnet Ethereum");
// 🔭 block explorer URL
// const blockExplorer = targetNetwork.blockExplorer;

const drawerWidth = 264;
const transitionDuration = 969;
function App() {
    const location = useLocation();
    const [theme, toggleTheme] = useTheme();

    const config = useConfig();
    const { connect, error: errorMessage } = useConnect();
    const tryConnectInjected = () => connect({ connector: injected() });

    const bondIndexes = [];

    const [wrongNetworkToastId, setWrongNetworkToastId] = useState(null);
    const [isSidebarExpanded, setIsSidebarExpanded] = useState(false);
    const [mobileOpen, setMobileOpen] = useState(false);

    const { address = "", chainId: addressChainId, isConnected, isReconnecting } = useAccount();

    const provider = usePublicClient();
    const chainId  = useChainId();

    const isSmallerScreen = useMediaQuery("(max-width: 1047px)");
    const isSmallScreen = useMediaQuery("(max-width: 600px)");

    useEffect(() => {
        if (shouldTriggerSafetyCheck()) {
            toast.success("Safety Check: Always verify you're on app.dao.ghostchain.io!", { duration: 5000 });
        }
    }, []);

    useEffect(() => {
        if (isConnected && chainId !== addressChainId) {
            const toastId = toast.loading("You are connected to wrong network. Use one of the deployed networks please.", {
                position: 'bottom-right'
            });
            setWrongNetworkToastId(toastId);
        } else {
            if (wrongNetworkToastId) {
                toast.dismiss(wrongNetworkToastId);
                setWrongNetworkToastId(null);
            }
        }
    }, [chainId, addressChainId, isConnected])

    useEffect(() => {
        if (errorMessage) {
            toast.error("No injected connectors found in your browser. Download Metamask extension or visit EIP-1193 for more details.", { duration: 5000 });
        }
    }, [errorMessage]);

    const handleDrawerToggle = () => {
        setMobileOpen(!mobileOpen);
    };

    const handleSidebarClose = () => {
        setIsSidebarExpanded(false);
    };

    const themeMode = theme === "light" ? lightTheme : theme === "dark" ? darkTheme : gTheme;

    const chainExists = isNetworkAvailable(chainId, addressChainId);

    useEffect(() => {
        if (isSidebarExpanded) handleSidebarClose();
    }, [location]);

    return (
        <StyledDiv>
            <ThemeProvider theme={themeMode}>
                <CssBaseline />
                <div className={`app ${isSmallerScreen && "tablet"} ${isSmallScreen && "mobile"} ${theme}`}>
                    <Toaster>{t => <Messages toast={t} />}</Toaster>
                    <TopBar
                        wrongNetworkToastId={wrongNetworkToastId}
                        setWrongNetworkToastId={setWrongNetworkToastId}
                        address={address}
                        chainId={addressChainId ? addressChainId : chainId}
                        chainExists={chainExists}
                        handleDrawerToggle={handleDrawerToggle}
                        connect={tryConnectInjected}
                    />
                    <nav className={classes.drawer}>
                        {isSmallerScreen ? (
                            <NavDrawer chainId={chainId} addressChainId={addressChainId} mobileOpen={mobileOpen} handleDrawerToggle={handleDrawerToggle} />
                        ) : (
                            <Sidebar chainId={chainId} addressChainId={addressChainId} />
                        )}
                    </nav>

                    <div className={`${classes.content} ${isSmallerScreen && classes.contentShift}`}>
                        <Suspense fallback={<div></div>}>
                            <Routes>
                                <Route path="/" element={<Navigate to={chainExists ? "/dashboard" : "/empty"} />} />
                                {chainExists &&
                                    <>
                                        <Route path="/dashboard" element={<TreasuryDashboard chainId={addressChainId ? addressChainId : chainId} />} />
                                        <Route path="/bonds" element={<Bonds connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
                                        <Route path="/bonds/:id" element={<BondModalContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
                                        <Route path="/stake" element={<StakeContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId}/>} />
                                        <Route path="/faucet" element={<Faucet config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
                                        <Route path="/bridge" element={<Bridge config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
                                        <Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
                                    </>
                                }
                                <Route path="/empty" element={<NotFound
                                    wrongNetworkToastId={wrongNetworkToastId}
                                    setWrongNetworkToastId={setWrongNetworkToastId}
                                    chainId={addressChainId ? addressChainId : chainId}
                                    chainExists={chainExists}
                                />} />
                                <Route path="*" element={<NotFound
                                    wrongNetworkToastId={wrongNetworkToastId}
                                    setWrongNetworkToastId={setWrongNetworkToastId}
                                    chainId={addressChainId ? addressChainId : chainId}
                                    chainExists={chainExists}
                                />} />
                            </Routes>
                        </Suspense>
                    </div>
                </div>
            </ThemeProvider>
        </StyledDiv>
    );
}

export default App;
