import { createRouter, createWebHistory } from 'vue-router';
import { getTeam } from './data/team';
import generateRoutes from './objects/generateRoutes';

let router = createRouter({
	history: createWebHistory('/dashboard/'),
	routes: [
		{
			path: '/',
			name: 'Home',
			component: () => import('./pages/Home.vue'),
			beforeEnter: (to, from, next) => {
				next({
					name: 'Welcome',
					query: {
						is_redirect: true,
					},
				});
			},
		},
		{
			path: '/welcome',
			name: 'Welcome',
			component: () => import('./pages/Welcome.vue'),
			meta: { hideSidebar: true },
		},
		{
			path: '/login',
			name: 'Login',
			component: () => import('./pages/LoginSignup.vue'),
			meta: { isLoginPage: true },
		},
		{
			path: '/signup',
			name: 'Signup',
			component: () => import('./pages/LoginSignup.vue'),
			meta: { isLoginPage: true },
		},
		{
			path: '/site-login',
			name: 'Site Login',
			component: () => import('./pages/SiteLogin.vue'),
			meta: { hideSidebar: true },
		},
		{
			path: '/setup-account/:requestKey/:joinRequest?',
			name: 'Setup Account',
			component: () => import('./pages/SetupAccount.vue'),
			props: true,
			meta: { isLoginPage: true },
		},
		{
			path: '/reset-password/:requestKey',
			name: 'Reset Password',
			component: () => import('./pages/ResetPassword.vue'),
			props: true,
			meta: { isLoginPage: true },
		},
		{
			path: '/checkout/:secretKey',
			name: 'Checkout',
			component: () => import('./views/checkout/Checkout.vue'),
			props: true,
			meta: {
				isLoginPage: true,
			},
		},
		{
			path: '/subscription/:site?',
			name: 'Subscription',
			component: () => import('./views/checkout/Subscription.vue'),
			props: true,
			meta: {
				hideSidebar: true,
			},
		},
		{
			name: 'Enable2FA',
			path: '/enable-2fa',
			component: () => import('./pages/Enable2FA.vue'),
			props: true,
			meta: {
				hideSidebar: true,
			},
		},
		{
			name: 'New Site',
			path: '/sites/new',
			component: () => import('./pages/NewSite.vue'),
		},
		{
			name: 'Release Group New Site',
			path: '/groups/:bench/sites/new',
			component: () => import('./pages/NewSite.vue'),
			props: true,
		},
		{
			name: 'New Release Group',
			path: '/groups/new',
			component: () => import('./pages/NewReleaseGroup.vue'),
		},
		{
			name: 'Server New Release Group',
			path: '/servers/:server/groups/new',
			component: () => import('./pages/NewReleaseGroup.vue'),
			props: true,
		},
		{
			name: 'New Server',
			path: '/servers/new',
			component: () => import('./pages/NewServer.vue'),
		},
		{
			name: 'Jsite Servers',
			path: '/jsite-servers',
			component: () => import('./pages/ListPage.vue'),
			props: route => {
				return { objectType: 'Jsite Server', ...route.params };
			}
		},
		{
			name: 'New Jsite Server',
			path: '/jsite-servers/new',
			component: () => import('./pages/NewJsiteServer.vue'),
		},
		{
			name: 'Jsite Server Detail',
			path: '/jsite-servers/:name',
			component: () => import('./pages/DetailPage.vue'),
			props: route => {
				return { objectType: 'Jsite Server', ...route.params };
			}
		},
		{
			name: 'Jsite Domain List',
			path: '/domains',
			component: () => import('./pages/ListPage.vue'),
			props: route => {
				return { objectType: 'Jsite Domain', ...route.params };
			}
		},
		{
			name: 'New Jsite Domain',
			path: '/domains/new',
			component: () => import('./pages/NewJsiteDomain.vue'),
		},
		{
			name: 'Jsite Domain Detail',
			path: '/domains/:name',
			component: () => import('./pages/DetailPage.vue'),
			props: route => {
				return { objectType: 'Jsite Domain', ...route.params };
			}
		},
		{
			name: 'Billing',
			path: '/billing',
			component: () => import('./pages/Billing.vue'),
			children: [
				{
					name: 'BillingOverview',
					path: '',
					component: () => import('./pages/BillingOverview.vue'),
				},
				{
					name: 'BillingInvoices',
					path: 'invoices',
					component: () => import('./pages/BillingInvoices.vue'),
				},
				{
					name: 'BillingOrders',
					path: 'orders',
					component: () => import('./pages/BillingOrders.vue'),
				},
				{
					name: 'BillingBalances',
					path: 'balances',
					component: () => import('./pages/BillingBalances.vue'),
				},
				{
					name: 'BillingPaymentMethods',
					path: 'payment-methods',
					component: () => import('./pages/BillingPaymentMethods.vue'),
				},
				{
					name: 'BillingMarketplacePayouts',
					path: 'payouts',
					component: () => import('./pages/BillingMarketplacePayouts.vue'),
				},
				{
					name: 'BillingMpesaInvoices',
					path: 'mpesa-invoices',
					component: () => import('./pages/BillingMpesaInvoices.vue'),
				},
			],
		},
		{
			path: '/settings',
			name: 'Settings',
			redirect: { name: 'SettingsProfile' },
			component: () => import('./pages/Settings.vue'),
			children: [
				{
					name: 'SettingsProfile',
					path: 'profile',
					component: () =>
						import('./components/settings/profile/ProfileSettings.vue'),
				},
				{
					name: 'SettingsTeam',
					path: 'team',
					component: () => import('./components/settings/TeamSettings.vue'),
				},
				{
					name: 'SettingsDeveloper',
					path: 'developer',
					component: () =>
						import('./components/settings/DeveloperSettings.vue'),
				},
				{
					name: 'SettingsPermission',
					path: 'permissions',
					component: () =>
						import('./components/settings/SettingsPermissions.vue'),
					redirect: { name: 'SettingsPermissionRoles' },
					children: [
						{
							path: 'roles',
							name: 'SettingsPermissionRoles',
							component: () => import('./components/settings/RoleList.vue'),
						},
						{
							name: 'SettingsPermissionRolePermissions',
							path: 'roles/:roleId',
							component: () =>
								import('./components/settings/RolePermissions.vue'),
							props: true,
						},
					],
				},
			],
		},
		{
			name: 'Partner Portal',
			path: '/partners',
			redirect: { name: 'PartnerOverview' },
			component: () => import('./pages/Partners.vue'),
			children: [
				{
					name: 'PartnerOverview',
					path: 'overview',
					component: () => import('./components/partners/PartnerOverview.vue'),
				},
				{
					name: 'PartnerCustomers',
					path: 'customers',
					component: () => import('./components/partners/PartnerCustomers.vue'),
				},
				{
					name: 'PartnerApprovalRequests',
					path: 'approval-requests',
					component: () =>
						import('./components/partners/PartnerApprovalRequests.vue'),
				},
				{
					name: 'LocalPaymentSetup',
					path: 'local-payment-setup',
					component: () =>
						import('./components/partners/PartnerLocalPaymentSetup.vue'),
				},
			],
		},
		{
			name: 'Signup Create Site',
			path: '/create-site',
			redirect: { name: 'Home' },
			children: [
				{
					name: 'SignupAppSelector',
					path: 'app-selector',
					component: () => import('./pages/saas/AppSelector.vue'),
					meta: { hideSidebar: true },
				},
				{
					name: 'SignupSetup',
					path: ':productId/setup',
					component: () => import('./pages/saas/SetupSite.vue'),
					props: true,
					meta: { hideSidebar: true },
				},
				{
					name: 'SignupLoginToSite',
					path: ':productId/login-to-site',
					component: () => import('./pages/saas/LoginToSite.vue'),
					props: true,
					meta: { hideSidebar: true },
				},
			],
		},
		{
			name: 'Impersonate',
			path: '/impersonate/:teamId',
			component: () => import('./pages/Impersonate.vue'),
			props: true,
		},
		{
			name: 'InstallApp',
			path: '/install-app/:app',
			component: () => import('./pages/InstallApp.vue'),
			props: true,
		},
		{
			name: 'CreateSiteForMarketplaceApp',
			path: '/create-site/:app',
			component: () => import('./pages/CreateSiteForMarketplaceApp.vue'),
			props: true,
		},
		{
			path: '/developer-reply/:marketplaceApp/:reviewId',
			name: 'ReplyMarketplaceApp',
			component: () =>
				import('./components/marketplace/ReplyMarketplaceApp.vue'),
			props: true,
		},
		{
			path: '/sql-playground',
			name: 'SQL Playground',
			component: () =>
				import('./pages/devtools/database/DatabaseSQLPlayground.vue'),
		},
		{
			path: '/database-analyzer',
			name: 'DB Analyzer',
			component: () => import('./pages/devtools/database/DatabaseAnalyzer.vue'),
		},
		{
			path: '/log-browser/:mode?/:docName?/:logId?',
			name: 'Log Browser',
			component: () => import('./pages/devtools/log-browser/LogBrowser.vue'),
			props: true,
		},
		{
			path: '/recharge',
			name: 'RechargeCredits',
			component: () => import('./pages/RechargeCredits.vue'),
			meta: { 
				requiresAuth: true 
			},
		},
		...generateRoutes(),
		{
			path: '/:pathMatch(.*)*',
			name: '404',
			component: () => import('./views/general/404.vue'),
		},
	],
});

router.beforeEach(async (to, from, next) => {
	let isLoggedIn =
		document.cookie.includes('user_id') &&
		!document.cookie.includes('user_id=Guest');
	let goingToLoginPage = to.matched.some((record) => record.meta.isLoginPage);

	if (isLoggedIn) {
		await waitUntilTeamLoaded();
		let $team = getTeam();
		let onboardingComplete = $team.pg.onboarding.complete;
		let defaultRoute = 'Site List';
		let onboardingRoute = 'Welcome';

		// identify user in posthog
		if (window.posthog?.__loaded) {
			try {
				window.posthog.identify($team.pg.user, {
					app: 'jingrow_cloud',
				});
			} catch (e) {
				console.error(e);
			}
		}

		// if team owner/admin enforce 2fa and user has not enabled 2fa, redirect to enable 2fa
		const Enable2FARoute = 'Enable2FA';
		if (
			to.name !== Enable2FARoute &&
			!$team.pg.is_desk_user &&
			$team.pg.enforce_2fa &&
			!$team.pg.user_info.is_2fa_enabled
		) {
			next({ name: Enable2FARoute });
			return;
		}

		// if team owner/admin doesn't enforce 2fa don't allow user to visit Enable2FA route
		if (to.name === Enable2FARoute && !$team.pg.enforce_2fa) {
			next({ name: defaultRoute });
			return;
		}

		if (
			!onboardingComplete &&
			(to.name.startsWith('Release Group') || to.name.startsWith('Server'))
		) {
			next({ name: onboardingRoute });
			return;
		}

		if (goingToLoginPage) {
			if (to.name == 'Signup' && to.query?.product) {
				next({
					name: 'SignupSetup',
					params: { productId: to.query.product },
				});
			}
			next({ name: defaultRoute });
		} else {
			next();
		}
	} else {
		if (goingToLoginPage) {
			next();
		} else {
			if (to.name == 'Site Login') {
				next();
			} else {
				next({ name: 'Login', query: { redirect: to.href } });
			}
		}
	}
});

function waitUntilTeamLoaded() {
	return new Promise((resolve) => {
		let interval = setInterval(() => {
			let team = getTeam();
			if (team?.pg) {
				clearInterval(interval);
				resolve();
			}
		}, 100);
	});
}

export default router;
