import axios from "axios";
import { createApp, defineAsyncComponent } from "vue";
import { createRouter, createWebHashHistory } from "vue-router";
import { createI18n } from "vue-i18n";
import vClickOutside from "click-outside-vue3";
import "./style.css";
import "./fonts/RobotoMonoNerdFont/font.css";
import { ensureCodec2ScriptsLoaded } from "./js/Codec2Loader";

import App from "./components/App.vue";
import en from "./locales/en.json";
import de from "./locales/de.json";
import ru from "./locales/ru.json";

// init i18n
const i18n = createI18n({
    legacy: false,
    locale: "en",
    fallbackLocale: "en",
    messages: {
        en,
        de,
        ru,
    },
});

// init vuetify
import { createVuetify } from "vuetify";
const vuetify = createVuetify();

// provide axios globally
window.axios = axios;

// setup global axios interceptor for auth errors
axios.interceptors.response.use(
    (response) => response,
    (error) => {
        if (error.response?.status === 401 || error.response?.status === 403) {
            // only redirect if we're not already on the auth page
            if (router.currentRoute.value.name !== "auth") {
                router.push("/auth");
            }
        }
        return Promise.reject(error);
    }
);

const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            name: "auth",
            path: "/auth",
            component: defineAsyncComponent(() => import("./components/auth/AuthPage.vue")),
        },
        {
            path: "/",
            redirect: "/messages",
        },
        {
            name: "about",
            path: "/about",
            component: defineAsyncComponent(() => import("./components/about/AboutPage.vue")),
        },
        {
            name: "interfaces",
            path: "/interfaces",
            component: defineAsyncComponent(() => import("./components/interfaces/InterfacesPage.vue")),
        },
        {
            name: "interfaces.add",
            path: "/interfaces/add",
            component: defineAsyncComponent(() => import("./components/interfaces/AddInterfacePage.vue")),
        },
        {
            name: "interfaces.edit",
            path: "/interfaces/edit",
            component: defineAsyncComponent(() => import("./components/interfaces/AddInterfacePage.vue")),
            props: {
                interface_name: String,
            },
        },
        {
            name: "messages",
            path: "/messages/:destinationHash?",
            props: true,
            component: defineAsyncComponent(() => import("./components/messages/MessagesPage.vue")),
        },
        {
            name: "map",
            path: "/map",
            component: defineAsyncComponent(() => import("./components/map/MapPage.vue")),
        },
        {
            name: "messages-popout",
            path: "/popout/messages/:destinationHash?",
            props: true,
            meta: { popoutType: "conversation", isPopout: true },
            component: defineAsyncComponent(() => import("./components/messages/MessagesPage.vue")),
        },
        {
            name: "network-visualiser",
            path: "/network-visualiser",
            component: defineAsyncComponent(() => import("./components/network-visualiser/NetworkVisualiserPage.vue")),
        },
        {
            name: "nomadnetwork",
            path: "/nomadnetwork/:destinationHash?",
            props: true,
            component: defineAsyncComponent(() => import("./components/nomadnetwork/NomadNetworkPage.vue")),
        },
        {
            name: "archives",
            path: "/archives",
            component: defineAsyncComponent(() => import("./components/archives/ArchivesPage.vue")),
        },
        {
            name: "nomadnetwork-popout",
            path: "/popout/nomadnetwork/:destinationHash?",
            props: true,
            meta: { popoutType: "nomad", isPopout: true },
            component: defineAsyncComponent(() => import("./components/nomadnetwork/NomadNetworkPage.vue")),
        },
        {
            name: "propagation-nodes",
            path: "/propagation-nodes",
            component: defineAsyncComponent(() => import("./components/propagation-nodes/PropagationNodesPage.vue")),
        },
        {
            name: "ping",
            path: "/ping",
            component: defineAsyncComponent(() => import("./components/ping/PingPage.vue")),
        },
        {
            name: "rncp",
            path: "/rncp",
            component: defineAsyncComponent(() => import("./components/rncp/RNCPPage.vue")),
        },
        {
            name: "rnstatus",
            path: "/rnstatus",
            component: defineAsyncComponent(() => import("./components/rnstatus/RNStatusPage.vue")),
        },
        {
            name: "rnprobe",
            path: "/rnprobe",
            component: defineAsyncComponent(() => import("./components/rnprobe/RNProbePage.vue")),
        },
        {
            name: "translator",
            path: "/translator",
            component: defineAsyncComponent(() => import("./components/translator/TranslatorPage.vue")),
        },
        {
            name: "forwarder",
            path: "/forwarder",
            component: defineAsyncComponent(() => import("./components/forwarder/ForwarderPage.vue")),
        },
        {
            name: "profile.icon",
            path: "/profile/icon",
            component: defineAsyncComponent(() => import("./components/profile/ProfileIconPage.vue")),
        },
        {
            name: "settings",
            path: "/settings",
            component: defineAsyncComponent(() => import("./components/settings/SettingsPage.vue")),
        },
        {
            name: "identities",
            path: "/identities",
            component: defineAsyncComponent(() => import("./components/settings/IdentitiesPage.vue")),
        },
        {
            name: "blocked",
            path: "/blocked",
            component: defineAsyncComponent(() => import("./components/blocked/BlockedPage.vue")),
        },
        {
            name: "tools",
            path: "/tools",
            component: defineAsyncComponent(() => import("./components/tools/ToolsPage.vue")),
        },
        {
            name: "call",
            path: "/call",
            component: defineAsyncComponent(() => import("./components/call/CallPage.vue")),
        },
    ],
});

router.beforeEach(async (to, from, next) => {
    try {
        const response = await window.axios.get("/api/v1/auth/status");
        const status = response.data;

        if (!status.auth_enabled) {
            next();
            return;
        }

        if (status.authenticated) {
            if (to.name === "auth") {
                next("/");
            } else {
                next();
            }
            return;
        }

        if (to.name === "auth") {
            next();
            return;
        }

        next("/auth");
    } catch (e) {
        if (e.response?.status === 401 || e.response?.status === 403) {
            next("/auth");
        } else {
            next();
        }
    }
});

async function bootstrap() {
    await ensureCodec2ScriptsLoaded();
    createApp(App).use(router).use(vuetify).use(i18n).use(vClickOutside).mount("#app");
}

bootstrap();
