import VueRouter from 'vue-router';

import auth from '../api/auth';
import login from './login/login.routes';
import dashboard from './dashboard/dashboard.routes';
import authRoute from './auth/auth.routes';
import { frontendURL } from '../helper/URLHelper';

const routes = [
  ...login.routes,
  ...dashboard.routes,
  ...authRoute.routes,
  {
    path: '/',
    redirect: '/app',
  },
];

window.roleWiseRoutes = {
  agent: [],
  administrator: [],
};

const getUserRole = ({ accounts } = {}, accountId) => {
  const currentAccount = accounts.find(account => account.id === accountId);
  return currentAccount ? currentAccount.role : null;
};

// generateRoleWiseRoute - updates window object with agent/admin route
const generateRoleWiseRoute = route => {
  route.forEach(element => {
    if (element.children) {
      generateRoleWiseRoute(element.children);
    }
    if (element.roles) {
      element.roles.forEach(roleEl => {
        window.roleWiseRoutes[roleEl].push(element.name);
      });
    }
  });
};
// Create a object of routes
// accessible by each role.
// returns an object with roles as keys and routeArr as values
generateRoleWiseRoute(routes);

export const router = new VueRouter({ mode: 'history', routes });

const unProtectedRoutes = ['login', 'auth_signup', 'auth_reset_password'];

const authIgnoreRoutes = [
  'auth_confirmation',
  'pushBack',
  'auth_password_edit',
];

function routeIsAccessibleFor(route, role) {
  return window.roleWiseRoutes[role].includes(route);
}

const routeValidators = [
  {
    protected: false,
    loggedIn: true,
    handler: () => {
      const user = auth.getCurrentUser();
      return `accounts/${user.account_id}/dashboard`;
    },
  },
  {
    protected: true,
    loggedIn: false,
    handler: () => 'login',
  },
  {
    protected: true,
    loggedIn: true,
    handler: to => {
      const user = auth.getCurrentUser();
      const userRole = getUserRole(user, Number(to.params.accountId));
      const isAccessible = routeIsAccessibleFor(to.name, userRole);
      return isAccessible ? null : `accounts/${to.params.accountId}/dashboard`;
    },
  },
  {
    protected: false,
    loggedIn: false,
    handler: () => null,
  },
];

export const validateAuthenticateRoutePermission = (to, from, next) => {
  const isLoggedIn = auth.isLoggedIn();
  const isProtectedRoute = !unProtectedRoutes.includes(to.name);
  const strategy = routeValidators.find(
    validator =>
      validator.protected === isProtectedRoute &&
      validator.loggedIn === isLoggedIn
  );
  const nextRoute = strategy.handler(to);
  return nextRoute ? next(frontendURL(nextRoute)) : next();
};

const validateRouteAccess = (to, from, next) => {
  if (
    window.chatwootConfig.signupEnabled !== 'true' &&
    to.meta &&
    to.meta.requireSignupEnabled
  ) {
    const user = auth.getCurrentUser();
    next(frontendURL(`accounts/${user.account_id}/dashboard`));
  }

  if (authIgnoreRoutes.includes(to.name)) {
    return next();
  }
  return validateAuthenticateRoutePermission(to, from, next);
};

// protecting routes
router.beforeEach((to, from, next) => {
  if (!to.name) {
    const user = auth.getCurrentUser();
    if (user) {
      return next(frontendURL(`accounts/${user.account_id}/dashboard`));
    }
    return next('/app/login');
  }

  return validateRouteAccess(to, from, next);
});

export default router;
