const _ = require('lodash');

const DEFAULT_USER_IP = '127.0.0.1';

const responseContext = {

    isAllowed(req) {
        return this.isSetup(req) ||
            this.matchesPath(req, '/restore') ||
            this.isInternal(req) ||
            this.hasOrganizations(req);
    },

    matchesPath(req, path) {
        const matches = [
            // в исходной форме
            path,
            // с закрывающим слэшом
            path.replace(/([\?#]|$)/, '/$1').replace(/\/\/([\?#]|$)/, '/$1'),
            // без закрывающего слэша
            path.replace(/\/([\?#]|$)/, '$1'),
        ];

        // с ведущим слэшом
        if (path.indexOf('/') !== 0 && !/https?:\/\//.test(path)) {
            matches.push(`/${path}`);
        }

        // с добавлением app root
        if (_.get(req, 'config.app.root')) {
            for (let i = matches.length - 1; i >= 0; i--) {
                if (matches[i].indexOf('/') === 0 && matches[i].indexOf('//') !== 0) {
                    matches.push(req.config.app.root + matches[i].substring(1));
                }
            }
        }

        if (req.path) {
            for (let i = 0; i < matches.length; i++) {
                if (req.path.indexOf(matches[i]) === 0) {
                    return true;
                }
            }
        }

        return false;
    },

    isSetup(req) {
        return this.matchesPath(req, '/setup');
    },

    isAdminPage(req) {
        return this.matchesPath(req, '/admin');
    },

    isHomePage(req) {
        return this.matchesPath(req, '/home');
    },

    isOnboardingPage(req) {
        return this.matchesPath(req, '/start');
    },

    isInternal(req) {
        const session = this.getSession(req);

        if (session) {
            return session.internal;
        }
    },

    isFeatureEnabled(req, featureName) {
        return _.get(req.context, `features.${featureName}.enabled`, false);
    },

    hasOrganizations(req) {
        const orgs = _.get(req, 'context.organizations');

        return !_.isEmpty(orgs);
    },

    getCurrentOrganization(req) {
        const state = this.getState(req);

        if (state && state.organization) {
            const orgs = _.get(req, 'context.organizations');

            return _.find(orgs, { id: Number(state.organization) });
        }
    },

    getCurrentOrganizationId(req) {
        const state = this.getState(req);

        return state && state.organization;
    },

    isResetRequired(req) {
        return _.get(req, 'context.state.reset_required');
    },

    getAuthData(req) {
        return _.get(req, 'context.auth');
    },

    isAuthorized(req) {
        return !_.get(req, 'context.auth.errorCode');
    },

    getSessionId(req) {
        return _.get(req, 'context.state.session');
    },

    getOrgIdFromSession(req) {
        const session = this.getSession(req);
        const orgIds = _.get(session, 'org_id', '');

        return orgIds.split(',')[0];
    },

    getSessions(req) {
        return _.get(req, 'context.sessions', {});
    },

    isSocialAccount(req) {
        const session = this.getSession(req);

        return session && session.is_social;
    },

    isLightAccount(req) {
        const session = this.getSession(req);

        return session && session.is_light;
    },

    getSession(req) {
        return _.get(req, 'context.session') || this.getSessions(req)[this.getSessionId(req)];
    },

    hasSession(req, id) {
        return Boolean(_.find(this.getSessions(req), { id }));
    },

    hasSessionWithEmail(req, email) {
        return Boolean(_.find(this.getSessions(req), ({ login }) => {
            const sessionEmail = login.indexOf('@') === -1 ? `${login}@yandex.ru` : login;

            return sessionEmail === email;
        }));
    },

    isServiceEnabled(req, serviceName) {
        const orgData = this.getCurrentOrganization(req) || {};
        const serviceData = _.find(orgData.services, { slug: serviceName });

        return serviceData && serviceData.enabled && serviceData.ready;
    },

    getServiceUrl(req, serviceName) {
        return _.get(req, `context.services.${serviceName}.url`);
    },

    getSessionLocale(req) {
        const session = this.getSession(req);

        return session ? session.locale : null;
    },

    getState(req) {
        return _.get(req, 'context.state');
    },

    getCurrentUser(req) {
        const users = _.get(req, 'context.users', {});

        return users[this.getSessionId(req)];
    },

    getCookie(req, name) {
        return _.get(req, ['cookies', name]);
    },

    getHost(req) {
        return req.headers['x-forwarded-host'] || req.headers.host;
    },

    getUrl(req, path) {
        return `https://${this.getHost(req)}/${(path || '').replace(/^\//, '')}`;
    },

    getUserIp(req) {
        return req.ip || _.get(req, 'connection.remoteAddress') || DEFAULT_USER_IP;
    },

    setCurrentOrganizationId(req, id) {
        _.set(req, 'context.state.organization', id);
    },
};

module.exports = responseContext;
