import { createRouter, createWebHistory } from "vue-router";
import Login from "@/views/Login.vue";

import { isAuthenticated } from "./authGuard";
import { loadAccountData } from "./accountGuard";
import { isSetup } from "./setupGuard";
import { abilityAndNavUpdate } from "./adminGuard";
import type { PermissionType, PermissionSection, PermissionModule } from "@/types/permissionTypes";
import { resetMemberStores, setMemberId } from "./memberGuard";
import { resetProtocolStores, setProtocolId } from "./protocolGuard";
import { resetNewsletterStores, setNewsletterId } from "./newsletterGuard";
import { config } from "../config";
import { setBackupPage } from "./backupGuard";

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: "/",
      redirect: { name: "admin" },
    },
    {
      path: "/login",
      name: "login",
      component: Login,
    },
    {
      path: "/setup",
      name: "setup",
      component: () => import("@/views/RouterView.vue"),
      beforeEnter: [isSetup],
      children: [
        {
          path: "",
          name: "setup-create",
          component: () => import("@/views/setup/Setup.vue"),
        },
        {
          path: "verify",
          name: "setup-verify",
          component: () => import("@/views/setup/Verify.vue"),
          props: (route) => ({ mail: route.query.mail, token: route.query.token }),
        },
      ],
    },
    {
      path: "/reset",
      name: "reset",
      component: () => import("@/views/RouterView.vue"),
      children: [
        {
          path: "",
          name: "reset-start",
          component: () => import("@/views/reset/Start.vue"),
        },
        {
          path: "reset",
          name: "reset-reset",
          component: () => import("@/views/reset/Reset.vue"),
          props: (route) => ({ mail: route.query.mail, token: route.query.token }),
        },
      ],
    },
    {
      path: "/invite",
      name: "invite",
      component: () => import("@/views/RouterView.vue"),
      children: [
        {
          path: "verify",
          name: "invite-verify",
          component: () => import("@/views/invite/Verify.vue"),
          props: (route) => ({ mail: route.query.mail, token: route.query.token }),
        },
      ],
    },
    {
      path: "/admin",
      name: "admin",
      component: () => import("@/views/admin/View.vue"),
      beforeEnter: [isAuthenticated],
      children: [
        {
          path: "",
          name: "admin-default",
          component: () => import("@/views/admin/ViewSelect.vue"),
        },
        {
          path: "club",
          name: "admin-club",
          component: () => import("@/views/RouterView.vue"),
          meta: { type: "read", section: "club" },
          beforeEnter: [abilityAndNavUpdate],
          children: [
            {
              path: "",
              name: "admin-club-default",
              component: () => import("@/views/admin/ViewSelect.vue"),
              meta: { type: "read", section: "club" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "members",
              name: "admin-club-member-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "club", module: "member" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-club-member",
                  component: () => import("@/views/admin/club/members/Member.vue"),
                  beforeEnter: [resetMemberStores],
                },
                {
                  path: ":memberId",
                  name: "admin-club-member-routing",
                  component: () => import("@/views/admin/club/members/MemberRouting.vue"),
                  beforeEnter: [setMemberId],
                  props: true,
                  children: [
                    {
                      path: "overview",
                      name: "admin-club-member-overview",
                      component: () => import("@/views/admin/club/members/MemberOverview.vue"),
                      props: true,
                    },
                    {
                      path: "membership",
                      name: "admin-club-member-membership",
                      component: () => import("@/views/admin/club/members/Membership.vue"),
                      props: true,
                    },
                    {
                      path: "communication",
                      name: "admin-club-member-communication",
                      component: () => import("@/views/admin/club/members/MemberCommunication.vue"),
                      props: true,
                    },
                    {
                      path: "awards",
                      name: "admin-club-member-awards",
                      component: () => import("@/views/admin/club/members/MemberAwards.vue"),
                      props: true,
                    },
                    {
                      path: "qualifications",
                      name: "admin-club-member-qualifications",
                      component: () => import("@/views/admin/club/members/MemberQualifications.vue"),
                      props: true,
                    },
                    {
                      path: "positions",
                      name: "admin-club-member-positions",
                      component: () => import("@/views/admin/club/members/MemberExecutivePositions.vue"),
                      props: true,
                    },
                    {
                      path: "edit",
                      name: "admin-club-member-edit",
                      component: () => import("@/views/admin/club/members/MemberEdit.vue"),
                      meta: { type: "update", section: "club", module: "member" },
                      beforeEnter: [abilityAndNavUpdate],
                      props: true,
                    },
                  ],
                },
              ],
            },
            {
              path: "calendar",
              name: "admin-club-calendar",
              component: () => import("@/views/admin/club/calendar/Calendar.vue"),
              meta: { type: "read", section: "club", module: "calendar" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "newsletter",
              name: "admin-club-newsletter-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "club", module: "newsletter" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-club-newsletter",
                  component: () => import("@/views/admin/club/newsletter/Newsletter.vue"),
                  beforeEnter: [resetNewsletterStores],
                },
                {
                  path: ":newsletterId",
                  name: "admin-club-newsletter-routing",
                  component: () => import("@/views/admin/club/newsletter/NewsletterRouting.vue"),
                  beforeEnter: [setNewsletterId],
                  props: true,
                  children: [
                    {
                      path: "overview",
                      name: "admin-club-newsletter-overview",
                      component: () => import("@/views/admin/club/newsletter/NewsletterOverview.vue"),
                      props: true,
                    },
                    {
                      path: "data",
                      name: "admin-club-newsletter-data",
                      component: () => import("@/views/admin/club/newsletter/NewsletterData.vue"),
                      props: true,
                    },
                    {
                      path: "recipients",
                      name: "admin-club-newsletter-recipients",
                      component: () => import("@/views/admin/club/newsletter/NewsletterRecipients.vue"),
                      props: true,
                    },
                    {
                      path: "dates",
                      name: "admin-club-newsletter-dates",
                      component: () => import("@/views/admin/club/newsletter/NewsletterDates.vue"),
                      props: true,
                    },
                    {
                      path: "printout",
                      name: "admin-club-newsletter-printout",
                      component: () => import("@/views/admin/club/newsletter/NewsletterPrintout.vue"),
                      props: true,
                    },
                  ],
                },
              ],
            },
            {
              path: "protocol",
              name: "admin-club-protocol-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "club", module: "protocol" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-club-protocol",
                  component: () => import("@/views/admin/club/protocol/Protocol.vue"),
                  beforeEnter: [resetProtocolStores],
                },
                {
                  path: ":protocolId",
                  name: "admin-club-protocol-routing",
                  component: () => import("@/views/admin/club/protocol/ProtocolRouting.vue"),
                  beforeEnter: [setProtocolId],
                  props: true,
                  children: [
                    {
                      path: "overview",
                      name: "admin-club-protocol-overview",
                      component: () => import("@/views/admin/club/protocol/ProtocolOverview.vue"),
                      props: true,
                    },
                    {
                      path: "presence",
                      name: "admin-club-protocol-presence",
                      component: () => import("@/views/admin/club/protocol/ProtocolPresence.vue"),
                      props: true,
                    },
                    {
                      path: "voting",
                      name: "admin-club-protocol-voting",
                      component: () => import("@/views/admin/club/protocol/ProtocolVoting.vue"),
                      props: true,
                    },
                    {
                      path: "decisions",
                      name: "admin-club-protocol-decisions",
                      component: () => import("@/views/admin/club/protocol/ProtocolDecisions.vue"),
                      props: true,
                    },
                    {
                      path: "agenda",
                      name: "admin-club-protocol-agenda",
                      component: () => import("@/views/admin/club/protocol/ProtocolAgenda.vue"),
                      props: true,
                    },
                    {
                      path: "printout",
                      name: "admin-club-protocol-printout",
                      component: () => import("@/views/admin/club/protocol/ProtocolPrintout.vue"),
                      props: true,
                    },
                  ],
                },
              ],
            },
            {
              path: "query-builder",
              name: "admin-club-query_builder",
              component: () => import("@/views/admin/club/query/Builder.vue"),
              meta: { type: "read", section: "club", module: "query" },
              beforeEnter: [abilityAndNavUpdate],
            },
          ],
        },
        {
          path: "settings",
          name: "admin-settings",
          component: () => import("@/views/RouterView.vue"),
          meta: { type: "read", section: "settings" },
          beforeEnter: [abilityAndNavUpdate],
          children: [
            {
              path: "",
              name: "admin-settings-default",
              component: () => import("@/views/admin/ViewSelect.vue"),
              meta: { type: "read", section: "settings" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "qualification",
              name: "admin-settings-qualification-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "qualification" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-qualification",
                  component: () => import("@/views/admin/configuration/qualification/Qualification.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-qualification-edit",
                  component: () => import("@/views/admin/configuration/qualification/QualificationEdit.vue"),
                  meta: { type: "update", section: "settings", module: "qualification" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "award",
              name: "admin-settings-award-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "award" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-award",
                  component: () => import("@/views/admin/configuration/award/Award.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-award-edit",
                  component: () => import("@/views/admin/configuration/award/AwardEdit.vue"),
                  meta: { type: "update", section: "settings", module: "award" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "executive-position",
              name: "admin-settings-executive_position-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "executive_position" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-executive_position",
                  component: () => import("@/views/admin/configuration/executivePosition/ExecutivePosition.vue"),
                  meta: { type: "read", section: "settings", module: "executive_position" },
                  beforeEnter: [abilityAndNavUpdate],
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-executive_position-edit",
                  component: () => import("@/views/admin/configuration/executivePosition/ExecutivePositionEdit.vue"),
                  meta: { type: "update", section: "settings", module: "executive_position" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "communication-type",
              name: "admin-settings-communication_type-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "communication_type" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-communication_type",
                  component: () => import("@/views/admin/configuration/communicationType/CommunicationType.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-communication_type-edit",
                  component: () => import("@/views/admin/configuration/communicationType/CommunicationTypeEdit.vue"),
                  meta: { type: "update", section: "settings", module: "communication_type" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "status",
              name: "admin-settings-membership_status-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "membership_status" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-membership_status",
                  component: () => import("@/views/admin/configuration/membershipStatus/MembershipStatus.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-membership_status-edit",
                  component: () => import("@/views/admin/configuration/membershipStatus/MembershipStatusEdit.vue"),
                  meta: { type: "update", section: "settings", module: "membership_status" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "salutation",
              name: "admin-settings-salutation-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "salutation" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-salutation",
                  component: () => import("@/views/admin/configuration/salutation/Salutation.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-salutation-edit",
                  component: () => import("@/views/admin/configuration/salutation/SalutationEdit.vue"),
                  meta: { type: "update", section: "settings", module: "salutation" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "calendar-type",
              name: "admin-settings-calendar_type-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "calendar_type" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-calendar_type",
                  component: () => import("@/views/admin/configuration/calendarType/CalendarType.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-calendar_type-edit",
                  component: () => import("@/views/admin/configuration/calendarType/CalendarTypeEdit.vue"),
                  meta: { type: "update", section: "settings", module: "calendar_type" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "query-store",
              name: "admin-settings-query_store",
              component: () => import("@/views/admin/configuration/queryStore/QueryStore.vue"),
              meta: { type: "read", section: "settings", module: "query_store" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "template",
              name: "admin-settings-template-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "settings", module: "template" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-settings-template",
                  component: () => import("@/views/admin/configuration/template/Template.vue"),
                },
                {
                  path: "info",
                  name: "admin-settings-template-info",
                  component: () => import("@/views/admin/configuration/template/UsageInfo.vue"),
                  props: true,
                },
                {
                  path: ":id/edit",
                  name: "admin-settings-template-edit",
                  component: () => import("@/views/admin/configuration/template/TemplateEdit.vue"),
                  meta: { type: "update", section: "settings", module: "template" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "template-usage",
              name: "admin-settings-template_usage",
              component: () => import("@/views/admin/configuration/templateUsage/TemplateUsage.vue"),
              meta: { type: "read", section: "settings", module: "template_usage" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "newsletter-config",
              name: "admin-settings-newsletter_config",
              component: () => import("@/views/admin/configuration/newsletterConfig/NewsletterConfig.vue"),
              meta: { type: "read", section: "settings", module: "newsletter_config" },
              beforeEnter: [abilityAndNavUpdate],
            },
          ],
        },
        {
          path: "user",
          name: "admin-user",
          component: () => import("@/views/RouterView.vue"),
          meta: { type: "read", section: "user" },
          beforeEnter: [abilityAndNavUpdate],
          children: [
            {
              path: "",
              name: "admin-user-default",
              component: () => import("@/views/admin/ViewSelect.vue"),
              meta: { type: "read", section: "user" },
              beforeEnter: [abilityAndNavUpdate],
            },
            {
              path: "user",
              name: "admin-user-user-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "user", module: "user" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-user-user",
                  component: () => import("@/views/admin/management/user/User.vue"),
                },
                {
                  path: "invites",
                  name: "admin-user-user-invites",
                  component: () => import("@/views/admin/management/user/Invite.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-user-user-edit",
                  component: () => import("@/views/admin/management/user/UserEdit.vue"),
                  meta: { type: "update", section: "user", module: "user" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
                {
                  path: ":id/permission",
                  name: "admin-user-user-permission",
                  component: () => import("@/views/admin/management/user/UserEditPermission.vue"),
                  meta: { type: "update", section: "user", module: "user" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
                {
                  path: ":id/roles",
                  name: "admin-user-user-roles",
                  component: () => import("@/views/admin/management/user/UserEditRoles.vue"),
                  meta: { type: "update", section: "user", module: "user" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "role",
              name: "admin-user-role-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "user", module: "role" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-user-role",
                  component: () => import("@/views/admin/management/role/Role.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-user-role-edit",
                  component: () => import("@/views/admin/management/role/RoleEdit.vue"),
                  meta: { type: "update", section: "user", module: "role" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
                {
                  path: ":id/permission",
                  name: "admin-user-role-permission",
                  component: () => import("@/views/admin/management/role/RoleEditPermission.vue"),
                  meta: { type: "update", section: "user", module: "role" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "webapi",
              name: "admin-user-webapi-route",
              component: () => import("@/views/RouterView.vue"),
              meta: { type: "read", section: "user", module: "webapi" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-user-webapi",
                  component: () => import("@/views/admin/management/webapi/Webapi.vue"),
                },
                {
                  path: ":id/edit",
                  name: "admin-user-webapi-edit",
                  component: () => import("@/views/admin/management/webapi/WebapiEdit.vue"),
                  meta: { type: "update", section: "user", module: "webapi" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
                {
                  path: ":id/permission",
                  name: "admin-user-webapi-permission",
                  component: () => import("@/views/admin/management/webapi/WebapiEditPermission.vue"),
                  meta: { type: "update", section: "user", module: "webapi" },
                  beforeEnter: [abilityAndNavUpdate],
                  props: true,
                },
              ],
            },
            {
              path: "backup",
              name: "admin-user-backup-route",
              component: () => import("@/views/admin/management/backup/BackupRouting.vue"),
              meta: { type: "read", section: "user", module: "backup" },
              beforeEnter: [abilityAndNavUpdate],
              children: [
                {
                  path: "",
                  name: "admin-user-backup",
                  redirect: { name: "admin-user-backup-generated" },
                },
                {
                  path: "generated",
                  name: "admin-user-backup-generated",
                  component: () => import("@/views/admin/management/backup/GeneratedBackup.vue"),
                  beforeEnter: [setBackupPage],
                },
                {
                  path: "uploads",
                  name: "admin-user-backup-uploaded",
                  component: () => import("@/views/admin/management/backup/UploadedBackup.vue"),
                  beforeEnter: [setBackupPage],
                },
              ],
            },
            {
              path: "version",
              name: "admin-user-version",
              component: () => import("@/views/admin/management/version/VersionDisplay.vue"),
            },
          ],
        },
        {
          path: ":pathMatch(.*)*",
          name: "admin-404",
          component: () => import("@/views/notFound.vue"),
        },
      ],
    },
    {
      path: "/account",
      name: "account",
      component: () => import("@/views/account/View.vue"),
      beforeEnter: [isAuthenticated],
      children: [
        {
          path: "",
          name: "account-default",
          component: () => import("@/views/account/ViewSelect.vue"),
        },
        {
          path: "me",
          name: "account-me",
          component: () => import("@/views/account/Me.vue"),
        },
        {
          path: "logindata",
          name: "account-logindata",
          component: () => import("@/views/account/LoginData.vue"),
        },
        {
          path: "permission",
          name: "account-permission",
          component: () => import("@/views/account/Permission.vue"),
        },
        {
          path: "administration",
          name: "account-administration",
          component: () => import("@/views/account/Administration.vue"),
        },
        {
          path: ":pathMatch(.*)*",
          name: "account-404",
          component: () => import("@/views/notFound.vue"),
        },
      ],
    },
    {
      path: "/public",
      name: "public",
      component: () => import("@/views/public/View.vue"),
      children: [
        {
          path: "",
          name: "public-default",
          component: () => import("@/views/notFound.vue"),
        },
        {
          path: "calendar",
          name: "public-calendar",
          component: () => import("@/views/public/calendar/Calendar.vue"),
        },
        {
          path: "calendar-explain",
          name: "public-calendar-explain",
          component: () => import("@/views/public/calendar/CalendarExplain.vue"),
        },
      ],
    },
    {
      path: "/docs",
      name: "docs",
      component: () => import("@/views/docs/View.vue"),
      beforeEnter: [isAuthenticated],
      props: true,
      children: [
        {
          path: "",
          name: "docs-default",
          component: () => import("@/views/docs/ViewSelect.vue"),
        },
        {
          path: ":page",
          name: "docs-page",
          component: () => import("@/views/docs/DocPage.vue"),
          props: true,
        },
      ],
    },
    {
      path: "/nopermissions",
      name: "nopermissions",
      component: () => import("@/views/NoPermission.vue"),
    },
    {
      path: "/:pathMatch(.*)*",
      name: "404",
      component: () => import("@/views/notFound.vue"),
    },
  ],
});

router.afterEach((to, from) => {
  document.title = config.app_name_overwrite || "FF Admin";
});

export default router;

declare module "vue-router" {
  interface RouteMeta {
    type?: PermissionType | "admin";
    section?: PermissionSection;
    module?: PermissionModule;
  }
}