import _ from 'lodash';

import App from 'components/App';
import SectionLayout from 'components/SectionLayout';

import Dashboard from 'components/Dashboard';
import Downloads from 'components/Downloads';
import Unknown from 'components/Unknown';
import OrgSetup from 'components/OrgSetup';
import Restore from 'components/Restore';
import { CreateUserWidget } from 'components/CreateUserWidget';

import AppActions from 'actions/App';
import PermissionStore from 'stores/Permissions';
import AuthStore from 'stores/Auth';

import Url from 'lib/Url';
import { redirectToForbidden } from 'lib2/redirectToForbidden';

const GROUP_MEMBER_TYPE_MAP = {
    users: 'user',
    departments: 'department',
    groups: 'group',
};

const config = _.get(window.ya, 'connect.config', {});
const appRoot = _.get(config, 'app.root', '/');

const routeStorage = {
    dashboard: {
        component: Dashboard,
        onEnter(nextState, replace, callback) {
            AppActions.Dashboard.showDashboard()
                .then(() => {
                    AppActions.Licenses.showPricing();
                    callback();
                });
        },
    },
};

let routes = [
    {
        path: appRoot,
        indexRoute: routeStorage.dashboard,
        childRoutes: [
            {
                path: 'home',
                indexRoute: routeStorage.dashboard,
            },
            {
                path: 'downloads',
                indexRoute: {
                    component: Downloads,
                    onEnter(nextState, replace, callback) {
                        AppActions.Common.performDefaultAction()
                            .then(callback);
                    },
                },
            },
            {
                path: 'setup',
                indexRoute: {
                    component: OrgSetup,
                    onEnter(nextState, replace, callback) {
                        AppActions.Common.performDefaultAction()
                            .then(callback);
                    },
                },
            },
            {
                path: 'restore',
                indexRoute: {
                    component: Restore,
                    onEnter(nextState, replace, callback) {
                        AppActions.Restore.showActiveChecks()
                            .then(callback);
                    },
                },
                childRoutes: [
                    {
                        path: 'new',
                        component: Restore,
                        onEnter(nextState, replace, callback) {
                            AppActions.Restore.showNewRequest()
                                .then(callback);
                        },
                    },
                    {
                        path: ':restoreId',
                        component: Restore,
                        onEnter(nextState, replace, callback) {
                            AppActions.Restore.showCheckStatus(nextState.params.restoreId)
                                .then(callback);
                        },
                    },
                ],
            },
            {
                path: 'admin/subscription/balance',
                onEnter() {
                    window.location.href = Url.getPath('balance');
                },
            },
            {
                path: 'admin/subscription/agreement',
                onEnter() {
                    if (!AuthStore.isInternal()) {
                        return redirectToForbidden();
                    }

                    const url = new URL('portal/balance/contract', window.location.origin);
                    const { searchParams } = new URL(window.location.href);
                    const retpath = searchParams.get('retpath');
                    const source = searchParams.get('source');

                    if (retpath) {
                        url.searchParams.set('retpath', retpath);
                    }

                    if (source) {
                        url.searchParams.set('source', source);
                    }

                    window.location.href = url.href;
                },
            },
            {
                path: 'admin/domains',
                indexRoute: {
                    onEnter() {
                        let url = Url.getServiceSettingsUrl('webmaster');
                        let from = Url.getQueryParam('from');

                        if (from) {
                            url += `?from=${from}`;
                        }

                        window.location.replace(url);
                    },
                },
                childRoutes: [
                    {
                        path: ':domain',
                        onEnter(nextState) {
                            window.location.replace(Url.getPath(
                                'services',
                                'webmaster',
                                'resources',
                                nextState.params.domain
                            ));
                        },
                    },
                ],
            },
            {
                path: 'admin/customization',
                childRoutes: [
                    {
                        path: 'dns',
                        onEnter() {
                            window.location.replace(Url.getServiceSettingsUrl('webmaster'));
                        },
                    },
                    {
                        path: 'tracker',
                        onEnter() {
                            window.location.replace(Url.getServiceSettingsUrl('tracker'));
                        },
                    },
                    {
                        path: 'mail',
                        onEnter() {
                            window.location.replace(Url.getServiceSettingsUrl('mail'));
                        },
                    },
                ],
            },
            {
                // ВНИМАНИЕ
                // Часть разделов из /admin копируется в /staff (см. ниже)
                // Вносите изменения аккуратно =)
                path: 'admin',
                component: App,
                onEnter(nextState, replace, callback) {
                    // раздел `/admin` остается только у внутрених админов, внутренних заместителей админов,
                    // внешних админов, внешних заместителей админов(те всех не внутрених пользователей)
                    if (!(AuthStore.isAdmin() || AuthStore.isInternalDeputyAdmin()) && AuthStore.isInternal()) {
                        return redirectToForbidden();
                    }

                    callback();
                },
                indexRoute: {
                    component: SectionLayout,
                    onEnter(nextState, replace, callback) {
                        if (!AuthStore.isIncompleteOrganization()) {
                            AppActions.OrgStructure.showRootDepartment()
                                .then(callback);
                        } else {
                            replace(Url.getPath('admin', 'domains'));
                            callback();
                        }
                    },
                },
                childRoutes: [
                    {
                        path: 'structure',
                        component: SectionLayout,
                        onEnter(nextState, replace, callback) {
                            if (!PermissionStore.allowsDepartmentsAdd()) {
                                return redirectToForbidden();
                            }

                            callback();
                        },
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                AppActions.OrgStructure.showRootDepartment()
                                    .then(callback);
                            },
                        },
                    },
                    {
                        path: 'groups',
                        component: SectionLayout,
                        onEnter(nextState, replace, callback) {
                            if (!PermissionStore.allowsGroupsAdd()) {
                                return redirectToForbidden();
                            }

                            callback();
                        },
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                AppActions.OrgStructure.showGroups('all')
                                    .then(callback);
                            },
                        },
                        childRoutes: [
                            {
                                path: 'admin',
                                indexRoute: {
                                    onEnter(nextState, replace, callback) {
                                        AppActions.OrgStructure.showGroups('admin')
                                            .then(callback);
                                    },
                                },
                                childRoutes: [
                                    {
                                        path: ':id/:memberRole/:memberType/:memberId',
                                        onEnter(nextState, replace, callback) {
                                            const { id, memberType, memberId } = nextState.params;
                                            const member = { id: memberId, type: GROUP_MEMBER_TYPE_MAP[memberType] };

                                            AppActions.OrgStructure.showGroupMember('admin', id, member)
                                                .then(callback);
                                        },
                                    },
                                    {
                                        path: ':id',
                                        onEnter(nextState, replace, callback) {
                                            AppActions.OrgStructure.showGroup('admin', nextState.params.id)
                                                .then(callback);
                                        },
                                    },
                                ],
                            },
                            {
                                path: 'member',
                                indexRoute: {
                                    onEnter(nextState, replace, callback) {
                                        AppActions.OrgStructure.showGroups('member')
                                            .then(callback);
                                    },
                                },
                                childRoutes: [
                                    {
                                        path: ':id/:memberRole/:memberType/:memberId',
                                        onEnter(nextState, replace, callback) {
                                            const { id, memberType, memberId } = nextState.params;
                                            const member = { id: memberId, type: GROUP_MEMBER_TYPE_MAP[memberType] };

                                            AppActions.OrgStructure.showGroupMember('member', id, member)
                                                .then(callback);
                                        },
                                    },
                                    {
                                        path: ':id',
                                        onEnter(nextState, replace, callback) {
                                            AppActions.OrgStructure.showGroup('member', nextState.params.id)
                                                .then(callback);
                                        },
                                    },
                                ],
                            },
                            {
                                path: ':id/:memberRole/:memberType/:memberId',
                                onEnter(nextState, replace, callback) {
                                    const { id, memberType, memberId } = nextState.params;
                                    const member = { id: memberId, type: GROUP_MEMBER_TYPE_MAP[memberType] };

                                    AppActions.OrgStructure.showGroupMember('all', id, member)
                                        .then(callback);
                                },
                            },
                            {
                                path: ':id',
                                component: SectionLayout,
                                onEnter(nextState, replace, callback) {
                                    AppActions.OrgStructure.showGroup('all', nextState.params.id)
                                        .then(callback);
                                },
                            },
                        ],
                    },
                    {
                        path: 'departments',
                        component: SectionLayout,
                        onEnter(nextState, replace, callback) {
                            if (!PermissionStore.allowsDepartmentsAdd()) {
                                return redirectToForbidden();
                            }

                            callback();
                        },
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                AppActions.OrgStructure.showRootDepartment()
                                    .then(callback);
                            },
                        },
                        childRoutes: [
                            {
                                path: ':id',
                                onEnter(nextState, replace, callback) {
                                    AppActions.OrgStructure.showDepartment(nextState.params.id)
                                        .then(callback);
                                },
                            },
                        ],
                    },
                    {
                        path: 'users',
                        component: SectionLayout,
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                if (!PermissionStore.allowsDepartmentsAdd()) {
                                    return redirectToForbidden();
                                }

                                AppActions.OrgStructure.showRootDepartment()
                                    .then(callback);
                            },
                        },
                        childRoutes: [
                            {
                                path: ':id',
                                onEnter(nextState, replace, callback) {
                                    AppActions.OrgStructure.showUser(nextState.params.id)
                                        .then(callback);
                                },
                            },
                        ],
                    },
                    {
                        path: 'profile',
                        component: SectionLayout,
                        onEnter(nextState, replace, callback) {
                            if (!PermissionStore.allowsOrganizationProfileEditing()) {
                                return redirectToForbidden();
                            }

                            AppActions.OrgStructure.showOrgProfile()
                                .then(callback);
                        },
                    },
                    {
                        path: 'subscription',
                        component: SectionLayout,
                        onEnter(nextState, replace, callback) {
                            AppActions.Subscription.showDetails()
                                .then(callback);
                        },
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                // /portal/admin/subscription - устаревший роут;
                                // поддерживаем редирект на Трекер для ссылок в письмах без хэша [DIR-7737]
                                window.location.replace(Url.getServiceSettingsUrl(window.location.hash || 'tracker'));
                                callback();
                            },
                        },
                        childRoutes: [
                            {
                                path: 'services',
                                onEnter(nextState, replace, callback) {
                                    window.location.replace(Url.getDashboardUrl());
                                    callback();
                                },
                            },
                            {
                                path: 'manage',
                                onEnter(nextState, replace, callback) {
                                    window.location.replace(Url.getServiceSettingsUrl('tracker'));
                                    callback();
                                },
                            },
                        ],
                    },
                    {
                        path: 'customization',
                        component: SectionLayout,
                        indexRoute: {
                            onEnter(nextState, replace, callback) {
                                replace(Url.getPath('admin', 'customization', 'general'));
                                callback();
                            },
                        },
                        childRoutes: [
                            {
                                path: 'admins',
                                onEnter(nextState, replace, callback) {
                                    if (!PermissionStore.allowsChangeRole()) {
                                        return redirectToForbidden();
                                    }

                                    AppActions.OrgSettings.showAdminList()
                                        .then(callback);
                                },
                                indexRoute: {
                                    onEnter(nextState, replace, callback) {
                                        AppActions.Common.performDefaultAction()
                                            .then(callback);
                                    },
                                },
                                childRoutes: [
                                    {
                                        path: ':id',
                                        onEnter(nextState, replace, callback) {
                                            AppActions.OrgSettings.showOrgAdmin(nextState.params.id)
                                                .then(callback);
                                        },
                                    },
                                ],
                            },
                            {
                                path: 'general',
                                onEnter(nextState, replace, callback) {
                                    if (AuthStore.isIncompleteOrganization()) {
                                        return redirectToForbidden();
                                    }

                                    return AppActions.Common.performDefaultAction()
                                        .then(callback);
                                },
                            },
                        ],
                    },
                ],
            },
            {
                path: 'iframe/create-user',
                component: CreateUserWidget,
            },
        ],
    },
    {
        // 404 обрабатывается только на клиенте
        path: '*',
        component: Unknown,
    },
];

// раздел /staff доступен только внутреним пользователям и админам
if (config.ui.staffModeEnabled && AuthStore.isInternal()) {
    // Общие секции для /admin и /staff
    const STAFF_SECTIONS = ['structure', 'departments', 'groups'];

    const [{ childRoutes: rootChildRoutes }] = routes;
    const adminRoutes = rootChildRoutes.find(route => route.path === 'admin');
    // удаляем проверку на админа в onEnter
    const { onEnter: unused0, ...staffRoutes } = adminRoutes;

    staffRoutes.path = 'staff';
    staffRoutes.childRoutes = staffRoutes.childRoutes
        // оставляем только нужные секции
        .filter(route => STAFF_SECTIONS.includes(route.path))
        // удаляем проверки, присущие админскому роутингу
        .map(({ onEnter: unused1, ...route }) => route);

    rootChildRoutes.push(staffRoutes);
}

// добавляем поддержку раздела `/portal` для совместимости с прежней схемой

routeStorage.adminPortal = {
    component: Unknown,
    onEnter(nextState, replace, callback) {
        if (AuthStore.isAdmin()) {
            replace(`${appRoot}admin`);
        }
        callback();
    },
};

if (appRoot === '/') {
    routes[0].childRoutes.push({
        path: 'portal',
        indexRoute: routeStorage.adminPortal,
    });
} else if (appRoot === '/portal/') {
    routes[0].indexRoute = routeStorage.adminPortal;
} else {
    routes.push({
        path: '/portal',
        indexRoute: routeStorage.adminPortal,
    });
}

// если корень приложения отличается от '/', то для совместимости с другими сервисами,
// ссылающимися на разделы Коннекта от '/', создаем корневой рут '/' и копируем в него
// необходимые подразделы
if (appRoot !== '/') {
    const rootPaths = [
        'home', 'setup',
    ];

    const rootRoute = { path: '/' };

    routes[0].path = routes[0].path.replace(/(^\/|\/$)/g, '');

    rootRoute.childRoutes = routes[0].childRoutes
        .filter(childRoute => rootPaths.indexOf(childRoute.path) !== -1)
        .slice()
        .concat(routes[0]);

    routes = [rootRoute].concat(routes.slice(1));
}

if (!config.app.isProd) {
    window.ya.connect.routes = routes;
}

export default routes;
