import AppLayout from "../layout/AppLayout.vue";
import AuthLayout from "../layout/AuthLayout.vue";
import { hydrateUser, userRef } from "../composables/useAuth";
import { useNavigation } from "../composables/useNavigation";
import { normalizePermissionList } from "../utils/permissionList";

import { createRouter, createWebHistory } from "vue-router";

export const coreRoutes = [
  {
    path: "/auth",
    component: AuthLayout,
    children: [
      {
        path: "login",
        name: "login",
        meta: { guest: true },
        component: () => import("../views/auth/LoginView.vue"),
      },
      {
        path: "oops",
        name: "auth-oops",
        component: () => import("../views/pages/Oops.vue"),
      },
      {
        path: "access",
        name: "auth-access",
        component: () => import("../views/pages/AccessDenied.vue"),
      },
    ],
  },
  {
    path: "/pages/notfound",
    component: AuthLayout,
    children: [
      {
        path: "",
        name: "pages-not-found",
        component: () => import("../views/pages/NotFound.vue"),
      },
    ],
  },
  {
    path: "/offers/public/:uuid",
    name: "offers-public-view",
    meta: {
      title: "Offer",
    },
    component: () =>
      import("../modules/offers/views/PublicOfferView.vue"),
  },
  {
    path: "/",
    name: "authenticated",
    component: AppLayout,
    meta: { requiresAuth: true },
    children: [
      {
        path: "",
        name: "authenticated-redirect-dashboard",
        redirect: "/dashboard",
      },
      {
        path: "dashboard",
        name: "dashboard",
        meta: {
          breadcrumb: ["Dashboard"],
          title: "Dashboard",
        },
        component: () => import("../views/dashboard/EcommerceView.vue"),
      },
      {
        path: "settings",
        name: "settings",
        meta: {
          breadcrumb: ["Settings"],
          title: "Settings",
        },
        component: () => import("../views/settings/SettingsRedirectView.vue"),
      },
      {
        path: "settings/organization",
        name: "settings-organization",
        meta: {
          breadcrumb: ["Settings", "Organization"],
          title: "Organization",
          permission: "settings.organization.view",
        },
        component: () => import("../views/organization/OrganizationProfileView.vue"),
      },
      {
        path: "settings/users",
        name: "settings-users",
        meta: {
          breadcrumb: ["Settings", "Users"],
          title: "Users",
          permission: "users.view",
        },
        component: () => import("../views/settings/UsersView.vue"),
      },
      {
        path: "settings/roles",
        name: "settings-roles",
        meta: {
          breadcrumb: ["Settings", "Roles"],
          title: "Roles",
          permission: "roles.view",
        },
        component: () => import("../views/settings/RolesManagementView.vue"),
      },
      {
        path: "settings/activity-log",
        name: "settings-activity-log",
        meta: {
          breadcrumb: ["Settings", "Activity log"],
          title: "Activity log",
          permission: "activitylog.view",
        },
        component: () => import("../views/settings/ActivityLogView.vue"),
      },
      {
        path: "settings/offers/catalog",
        name: "settings-offers-catalog",
        meta: {
          breadcrumb: ["Settings", "Offer catalog"],
          title: "Offer catalog",
          permission: "offers.catalog.manage",
        },
        component: () =>
          import("../modules/offers/views/OfferCatalogSettingsView.vue"),
      },
      {
        path: "settings/offers/templates",
        name: "settings-offers-templates",
        meta: {
          breadcrumb: ["Settings", "Offer templates"],
          title: "Offer templates",
          permission: "offers.templates.manage",
        },
        component: () =>
          import("../modules/offers/views/OfferTemplatesSettingsView.vue"),
      },
      {
        path: "superadmin",
        component: () => import("../views/superadmin/SuperadminLayout.vue"),
        meta: {
          breadcrumb: ["Superadmin"],
          title: "Superadmin",
          permission: "platform.superadmin",
        },
        children: [
          {
            path: "",
            redirect: "/superadmin/modules",
          },
          { path: "setup", redirect: "/superadmin/modules" },
          {
            path: "modules",
            name: "superadmin-modules",
            meta: {
              breadcrumb: ["Superadmin", "Modules"],
              title: "Modules",
            },
            component: () =>
              import("../views/superadmin/SuperadminModulesView.vue"),
          },
          {
            path: "navigation",
            name: "superadmin-navigation",
            meta: {
              breadcrumb: ["Superadmin", "Navigation"],
              title: "Navigation",
            },
            component: () =>
              import("../views/superadmin/SuperadminNavigationView.vue"),
          },
          {
            path: "appearance",
            name: "superadmin-appearance",
            meta: {
              breadcrumb: ["Superadmin", "Theme & layout"],
              title: "Theme & layout",
            },
            component: () =>
              import("../views/superadmin/MaestroAppearanceSettingsPanel.vue"),
          },
          {
            path: "branding",
            name: "superadmin-branding",
            meta: {
              breadcrumb: ["Superadmin", "Branding"],
              title: "Branding",
            },
            component: () =>
              import("../views/superadmin/SuperadminBrandingPanel.vue"),
          },
        ],
      },
    ],
  },
  {
    path: "/:pathMatch(.*)*",
    name: "fallback-not-found",
    component: () => import("../views/pages/NotFound.vue"),
  },
];

/**
 * Create the SPA router. Pass an optional callback to register customer routes
 * (e.g. router.addRoute) before the app mounts.
 *
 * @param {(router: import('vue-router').Router) => void} [extendRouter]
 *        Runs after CORE route records are prepared; typically used to {@link Router#addRoute}
 *        more children onto the authenticated layout (`name: authenticated`).
 */
export function createCoreRouter(extendRouter) {
  let bootstrapAuth = false;

  const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: coreRoutes,
  });

  router.beforeEach(async (to, from, next) => {
    if (!bootstrapAuth) {
      await hydrateUser();
      bootstrapAuth = true;
    }

    const isAuthed = Boolean(userRef.value);

    if (to.meta.requiresAuth && !isAuthed) {
      next({
        name: "login",
        query: { redirect: to.fullPath },
        replace: true,
      });

      return;
    }

    if (to.meta.guest && isAuthed) {
      next({ path: "/dashboard", replace: true });

      return;
    }

    const required = to.matched
      .map((r) => r.meta?.permission)
      .filter((p) => typeof p === "string");
    if (required.length && isAuthed && userRef.value) {
      const perms = normalizePermissionList(userRef.value.permissions);
      const allowed = required.every((p) => perms.includes(p));
      if (!allowed) {
        next({ name: "auth-access", replace: true });

        return;
      }
    }

    const moduleSlugs = to.matched
      .map((r) => r.meta?.module)
      .filter((s) => typeof s === "string");
    if (moduleSlugs.length && isAuthed && userRef.value) {
      const enabled = userRef.value.enabled_module_slugs ?? [];
      const moduleOk = moduleSlugs.every((slug) => enabled.includes(slug));
      if (!moduleOk) {
        next({ name: "auth-access", replace: true });

        return;
      }
    }

    if (to.meta.requiresAuth && isAuthed) {
      const { fetchNavigation } = useNavigation();
      await fetchNavigation();
    }

    next();
  });

  if (typeof extendRouter === "function") {
    extendRouter(router);
  }

  return router;
}
