import {
  createRouter,
  createWebHistory,
  createMemoryHistory,
  NavigationGuardNext,
  RouteLocationNormalized,
  RouteRecordRaw,
} from "vue-router";
import {
  accountsDBPromise,
  retrieveSettingsForActiveAccount,
} from "../db/index";
import { logger } from "../utils/logger";
import { Component as VueComponent } from "vue-facing-decorator";
import { defineComponent } from "vue";

/**
 *
 * @param to :RouteLocationNormalized
 * @param from :RouteLocationNormalized
 * @param next :NavigationGuardNext
 */
const enterOrStart = async (
  to: RouteLocationNormalized,
  from: RouteLocationNormalized,
  next: NavigationGuardNext,
) => {
  // one of the few times we use accountsDBPromise directly; try to avoid more usage
  const accountsDB = await accountsDBPromise;
  const num_accounts = await accountsDB.accounts.count();

  if (num_accounts > 0) {
    next();
  } else {
    next({ name: "start" });
  }
};

const routes: Array<RouteRecordRaw> = [
  {
    path: "/account",
    name: "account",
    component: () => {
      logger.log("Starting lazy load of AccountViewView");
      return new Promise((resolve) => {
        import("../views/AccountViewView.vue")
          .then((module) => {
            if (!module?.default) {
              logger.error(
                "AccountViewView module loaded but default export is missing",
                {
                  module: {
                    hasDefault: !!module?.default,
                    keys: Object.keys(module || {}),
                  },
                },
              );
              resolve(createErrorComponent());
              return;
            }

            // Check if the component has the required dependencies
            const component = module.default;
            logger.log("AccountViewView loaded, checking dependencies...", {
              componentName: component.name,
              hasVueComponent: component instanceof VueComponent,
              hasClass: typeof component === "function",
              type: typeof component,
            });

            resolve(component);
          })
          .catch((err) => {
            logger.error("Failed to load AccountViewView:", {
              error:
                err instanceof Error
                  ? {
                      name: err.name,
                      message: err.message,
                      stack: err.stack,
                    }
                  : err,
              type: typeof err,
            });

            resolve(createErrorComponent());
          });
      });
    },
    beforeEnter: async (to, from, next) => {
      try {
        logger.log("Account route beforeEnter guard starting");

        // Check if required dependencies are available
        const settings = await retrieveSettingsForActiveAccount();
        logger.log("Account route: settings loaded", {
          hasActiveDid: !!settings.activeDid,
          isRegistered: !!settings.isRegistered,
        });

        next();
      } catch (error) {
        logger.error("Error in account route beforeEnter:", {
          error:
            error instanceof Error
              ? {
                  name: error.name,
                  message: error.message,
                  stack: error.stack,
                }
              : error,
        });
        next({ name: "home" });
      }
    },
  },
  {
    path: "/claim/:id?",
    name: "claim",
    component: () => import("../views/ClaimView.vue"),
  },
  {
    path: "/claim-add-raw/:id?",
    name: "claim-add-raw",
    component: () => import("../views/ClaimAddRawView.vue"),
  },
  {
    path: "/claim-cert/:id",
    name: "claim-cert",
    component: () => import("../views/ClaimCertificateView.vue"),
  },
  {
    path: "/confirm-contact",
    name: "confirm-contact",
    component: () => import("../views/ConfirmContactView.vue"),
  },
  {
    path: "/confirm-gift/:id?",
    name: "confirm-gift",
    component: () => import("../views/ConfirmGiftView.vue"),
  },
  {
    path: "/contact-amounts",
    name: "contact-amounts",
    component: () => import("../views/ContactAmountsView.vue"),
  },
  {
    path: "/contact-edit/:did",
    name: "contact-edit",
    component: () => import("../views/ContactEditView.vue"),
  },
  {
    path: "/contact-gift",
    name: "contact-gift",
    component: () => import("../views/ContactGiftingView.vue"),
  },
  {
    path: "/contact-import/:jwt?",
    name: "contact-import",
    component: () => import("../views/ContactImportView.vue"),
  },
  {
    path: "/contact-qr",
    name: "contact-qr",
    component: () => import("../views/ContactQRScanShowView.vue"),
  },
  {
    path: "/contacts",
    name: "contacts",
    component: () => import("../views/ContactsView.vue"),
  },
  {
    path: "/did/:did?",
    name: "did",
    component: () => import("../views/DIDView.vue"),
  },
  {
    path: "/discover",
    name: "discover",
    component: () => import("../views/DiscoverView.vue"),
  },
  {
    path: "/gifted-details",
    name: "gifted-details",
    component: () => import("../views/GiftedDetailsView.vue"),
  },
  {
    path: "/help",
    name: "help",
    component: () => import("../views/HelpView.vue"),
  },
  {
    path: "/help-notifications",
    name: "help-notifications",
    component: () => import("../views/HelpNotificationsView.vue"),
  },
  {
    path: "/help-notification-types",
    name: "help-notification-types",
    component: () => import("../views/HelpNotificationTypesView.vue"),
  },
  {
    path: "/help-onboarding",
    name: "help-onboarding",
    component: () => import("../views/HelpOnboardingView.vue"),
  },
  {
    path: "/",
    name: "home",
    component: () => import("../views/HomeView.vue"),
  },
  {
    path: "/identity-switcher",
    name: "identity-switcher",
    component: () => import("../views/IdentitySwitcherView.vue"),
  },
  {
    path: "/import-account",
    name: "import-account",
    component: () => import("../views/ImportAccountView.vue"),
  },
  {
    path: "/import-derive",
    name: "import-derive",
    component: () => import("../views/ImportDerivedAccountView.vue"),
  },
  {
    path: "/invite-one",
    name: "invite-one",
    component: () => import("../views/InviteOneView.vue"),
  },
  {
    path: "/invite-one-accept/:jwt?",
    name: "InviteOneAcceptView",
    component: () => import("../views/InviteOneAcceptView.vue"),
  },
  {
    path: "/logs",
    name: "logs",
    component: () => import("../views/LogView.vue"),
  },
  {
    path: "/new-activity",
    name: "new-activity",
    component: () => import("../views/NewActivityView.vue"),
  },
  {
    path: "/new-edit-account",
    name: "new-edit-account",
    component: () => import("../views/NewEditAccountView.vue"),
  },
  {
    path: "/new-edit-project",
    name: "new-edit-project",
    component: () => import("../views/NewEditProjectView.vue"),
  },
  {
    path: "/new-identifier",
    name: "new-identifier",
    component: () => import("../views/NewIdentifierView.vue"),
  },
  {
    path: "/offer-details/:id?",
    name: "offer-details",
    component: () => import("../views/OfferDetailsView.vue"),
  },
  {
    path: "/onboard-meeting-list",
    name: "onboard-meeting-list",
    component: () => import("../views/OnboardMeetingListView.vue"),
  },
  {
    path: "/onboard-meeting-members/:groupId",
    name: "onboard-meeting-members",
    component: () => import("../views/OnboardMeetingMembersView.vue"),
  },
  {
    path: "/onboard-meeting-setup",
    name: "onboard-meeting-setup",
    component: () => import("../views/OnboardMeetingSetupView.vue"),
  },
  {
    path: "/project/:id?",
    name: "project",
    component: () => import("../views/ProjectViewView.vue"),
  },
  {
    path: "/projects",
    name: "projects",
    component: () => import("../views/ProjectsView.vue"),
    beforeEnter: enterOrStart,
  },
  {
    path: "/quick-action-bvc",
    name: "quick-action-bvc",
    component: () => import("../views/QuickActionBvcView.vue"),
  },
  {
    path: "/quick-action-bvc-begin",
    name: "quick-action-bvc-begin",
    component: () => import("../views/QuickActionBvcBeginView.vue"),
  },
  {
    path: "/quick-action-bvc-end",
    name: "quick-action-bvc-end",
    component: () => import("../views/QuickActionBvcEndView.vue"),
  },
  {
    path: "/recent-offers-to-user",
    name: "recent-offers-to-user",
    component: () => import("../views/RecentOffersToUserView.vue"),
  },
  {
    path: "/recent-offers-to-user-projects",
    name: "recent-offers-to-user-projects",
    component: () => import("../views/RecentOffersToUserProjectsView.vue"),
  },
  {
    path: "/scan-contact",
    name: "scan-contact",
    component: () => import("../views/ContactScanView.vue"),
  },
  {
    path: "/search-area",
    name: "search-area",
    component: () => import("../views/SearchAreaView.vue"),
  },
  {
    path: "/seed-backup",
    name: "seed-backup",
    component: () => import("../views/SeedBackupView.vue"),
  },
  {
    path: "/share-my-contact-info",
    name: "share-my-contact-info",
    component: () => import("../views/ShareMyContactInfoView.vue"),
  },
  {
    path: "/shared-photo",
    name: "shared-photo",
    component: () => import("../views/SharedPhotoView.vue"),
  },

  // /share-target is also an endpoint in the service worker

  {
    path: "/start",
    name: "start",
    component: () => import("../views/StartView.vue"),
  },
  {
    path: "/statistics",
    name: "statistics",
    component: () => import("../views/StatisticsView.vue"),
  },
  {
    path: "/test",
    name: "test",
    component: () => import("../views/TestView.vue"),
  },
  {
    path: "/user-profile/:id?",
    name: "user-profile",
    component: () => import("../views/UserProfileView.vue"),
  },
  {
    path: "/deep-link-error",
    name: "deep-link-error",
    component: () => import("../views/DeepLinkErrorView.vue"),
    meta: {
      title: "Invalid Deep Link",
      requiresAuth: false,
    },
  },
];

const isElectron = window.location.protocol === "file:";
const initialPath = isElectron
  ? window.location.pathname.split("/dist-electron/www/")[1] || "/"
  : window.location.pathname;

const history = isElectron
  ? createMemoryHistory() // Memory history for Electron
  : createWebHistory("/"); // Add base path for web apps

/** @type {*} */
const router = createRouter({
  history,
  routes,
});

// Replace initial URL to start at `/` if necessary
router.replace(initialPath || "/");

// Add global error handler
router.onError((error, to, from) => {
  logger.error("Router error:", {
    error:
      error instanceof Error
        ? {
            name: error.name,
            message: error.message,
            stack: error.stack,
          }
        : error,
    to: {
      name: to.name,
      path: to.path,
    },
    from: {
      name: from.name,
      path: from.path,
    },
  });

  // If it's a reference error during account view import, try to handle it gracefully
  if (error instanceof ReferenceError && to.name === "account") {
    logger.error("Account view import error:", {
      error:
        error instanceof Error
          ? {
              name: error.name,
              message: error.message,
              stack: error.stack,
            }
          : error,
    });
    // Instead of redirecting, let the component's error handling take over
    return;
  }
});

// Add navigation guard for debugging
router.beforeEach((to, from, next) => {
  logger.log("Navigation debug:", {
    to: {
      fullPath: to.fullPath,
      path: to.path,
      name: to.name,
      params: to.params,
      query: to.query,
    },
    from: {
      fullPath: from.fullPath,
      path: from.path,
      name: from.name,
      params: from.params,
      query: from.query,
    },
  });

  // For account route, try to preload the component
  if (to.name === "account") {
    logger.log("Preloading account component...");

    // Wrap in try-catch and use Promise
    new Promise((resolve) => {
      logger.log("Starting dynamic import of AccountViewView");

      // Add immediate try-catch to get more context
      try {
        const importPromise = import("../views/AccountViewView.vue");
        logger.log("Import initiated successfully");

        importPromise
          .then((module) => {
            try {
              logger.log("Import completed, analyzing module:", {
                moduleExists: !!module,
                moduleType: typeof module,
                moduleKeys: Object.keys(module || {}),
                hasDefault: !!module?.default,
                defaultType: module?.default
                  ? typeof module.default
                  : "undefined",
                defaultConstructor: module?.default?.constructor?.name,
                moduleContent: {
                  ...Object.fromEntries(
                    Object.entries(module).map(([key, value]) => [
                      key,
                      typeof value === "function"
                        ? "function"
                        : typeof value === "object"
                          ? Object.keys(value || {})
                          : typeof value,
                    ]),
                  ),
                },
              });

              if (!module?.default) {
                logger.error(
                  "AccountViewView preload: module loaded but default export is missing",
                  {
                    module: {
                      hasDefault: !!module?.default,
                      keys: Object.keys(module || {}),
                      moduleType: typeof module,
                      exports: Object.keys(module || {}).map((key) => ({
                        key,
                        type: typeof (module as any)[key],
                        value:
                          typeof (module as any)[key] === "function"
                            ? "function"
                            : typeof (module as any)[key] === "object"
                              ? Object.keys((module as any)[key] || {})
                              : (module as any)[key],
                      })),
                    },
                  },
                );
                resolve(null);
                return;
              }

              const component = module.default;

              // Try to safely inspect the component
              const componentDetails = {
                componentName: component.name,
                hasVueComponent: component instanceof VueComponent,
                hasClass: typeof component === "function",
                type: typeof component,
                properties: Object.keys(component),
                decorators: Object.getOwnPropertyDescriptor(
                  component,
                  "__decorators",
                ),
                vueOptions:
                  (component as any).__vccOpts ||
                  (component as any).options ||
                  null,
                setup: typeof (component as any).setup === "function",
                render: typeof (component as any).render === "function",
                components: (component as any).components
                  ? Object.keys((component as any).components)
                  : null,
                imports: Object.keys(module).filter((key) => key !== "default"),
              };

              logger.log("Successfully analyzed component:", componentDetails);
              resolve(component);
            } catch (analysisError) {
              logger.error("Error during component analysis:", {
                error:
                  analysisError instanceof Error
                    ? {
                        name: analysisError.name,
                        message: analysisError.message,
                        stack: analysisError.stack,
                        keys: Object.keys(analysisError),
                        properties: Object.getOwnPropertyNames(analysisError),
                      }
                    : analysisError,
                type: typeof analysisError,
                phase: "analysis",
              });
              resolve(null);
            }
          })
          .catch((err) => {
            logger.error("Failed to preload account component:", {
              error:
                err instanceof Error
                  ? {
                      name: err.name,
                      message: err.message,
                      stack: err.stack,
                      keys: Object.keys(err),
                      properties: Object.getOwnPropertyNames(err),
                    }
                  : err,
              type: typeof err,
              context: {
                routeName: to.name,
                routePath: to.path,
                fromRoute: from.name,
              },
              phase: "module-load",
            });
            resolve(null);
          });
      } catch (immediateError) {
        logger.error("Immediate error during import initiation:", {
          error:
            immediateError instanceof Error
              ? {
                  name: immediateError.name,
                  message: immediateError.message,
                  stack: immediateError.stack,
                  keys: Object.keys(immediateError),
                  properties: Object.getOwnPropertyNames(immediateError),
                }
              : immediateError,
          type: typeof immediateError,
          context: {
            routeName: to.name,
            routePath: to.path,
            fromRoute: from.name,
            importPath: "../views/AccountViewView.vue",
          },
          phase: "import",
        });
        resolve(null);
      }
    }).catch((err) => {
      logger.error("Critical error in account component preload:", {
        error:
          err instanceof Error
            ? {
                name: err.name,
                message: err.message,
                stack: err.stack,
              }
            : err,
        context: {
          routeName: to.name,
          routePath: to.path,
          fromRoute: from.name,
        },
        phase: "wrapper",
      });
    });
  }

  // Always call next() to continue navigation
  next();
});

function createErrorComponent() {
  return defineComponent({
    name: "AccountViewError",
    components: {
      // Add any required components here
    },
    setup() {
      const goHome = () => {
        router.push({ name: "home" });
      };

      return {
        goHome,
      };
    },
    template: `
      <section class="p-6 pb-24 max-w-3xl mx-auto">
        <h1 class="text-4xl text-center font-light mb-8">Error Loading Account View</h1>
        <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
          <strong class="font-bold">Failed to load account view.</strong>
          <span class="block sm:inline"> Please try refreshing the page.</span>
        </div>
        <div class="mt-4 text-center">
          <button @click="goHome" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
            Return to Home
          </button>
        </div>
      </section>
    `,
  });
}

export default router;