import _ from 'lodash';
import Immutable from 'immutable';
import { ReduceStore } from 'flux/utils';
import cookie from 'js-cookie';
import { ActionTypes } from 'constants/Common';
import { TRIAL_STATUS } from 'constants/Services';
import dispatcher from 'dispatcher';

import User from 'records/User';
import UserStore from 'stores/Users';
import SessionStore from 'stores/Sessions';
import ConfigStore from 'stores/Config';
import OrganizationStore from 'stores/Organizations';
import FeaturesStore from 'stores/Features';

import Url from 'lib/Url';

class AuthStore extends ReduceStore {
    getInitialState() {
        return new Immutable.Map();
    }

    reduce(state, action) {
        const { data, type } = action;

        switch (type) {
            case ActionTypes.RECEIVE_MIXED_DATA:
                return state.merge(data.state);
            default:
                return state;
        }
    }

    /**
     * Возвращает id авторизованого пользователя
     * @method  getUserId
     * @returns {String}
     */
    getUserId() {
        return this._state.get('session');
    }

    /**
     * Возвращает текущего пользователя
     * @method  getUser
     * @returns {User}
     */
    getUser() {
        return UserStore.get(this.getUserId()) || User.create(this.getSession());
    }

    getSession() {
        return SessionStore.get(this._state.get('session'));
    }

    getOrganizationId() {
        return this._state.get('organization') || _.get(window.ya, 'connect.initial.state.organization');
    }

    getOrganizationName() {
        const org = this.getOrganization();

        if (org) {
            return org.get('name');
        }
    }

    getOrganizationType() {
        const org = this.getOrganization();

        if (org) {
            return org.get('organization_type');
        }
    }

    isPartnerOrganization() {
        return this.getOrganizationType() === 'partner_organization';
    }

    getOrganization() {
        return OrganizationStore.get(this.getOrganizationId());
    }

    getDisplayName() {
        const session = this.getSession();

        if (session) {
            return session.getName();
        }
    }

    getLocale() {
        return ConfigStore.get('app.locale');
    }

    getCountry() {
        const session = this.getSession();

        if (session) {
            return session.get('country');
        }
    }

    getOrganizationDomain() {
        const org = this.getOrganization();

        if (org) {
            return org.getDomain();
        }
    }

    isInternal() {
        let session = this.getSession();

        if (session) {
            return session.isInternal();
        }

        const sessionId = _.get(window.ya, 'connect.initial.state.session');

        session = _.get(window.ya, `connect.initial.sessions.${sessionId}`, {});

        return session.internal;
    }

    isAdmin() {
        return this.isInternalAdmin() || this.isExternalAdmin();
    }

    isOrgOwner() {
        const ownerId = this.getOrganization().getAdminId();
        let session = this.getSession();

        if (!session) {
            const sessionId = _.get(window.ya, 'connect.initial.state.session');

            session = _.get(window.ya, `connect.initial.sessions.${sessionId}`, {});
        }

        return session.id === ownerId;
    }

    isDeputyAdmin() {
        return _.get(window.ya, 'connect.initial.currentUser.role') === 'deputy_admin';
    }

    isInternalDeputyAdmin() {
        // noop
    }

    isInternalAdmin() {
        return _.get(window.ya, 'connect.initial.currentUser.role') === 'admin';
    }

    /**
     * Является ли пользователь внешним администратором
     * @returns {Boolean}
     */
    isExternalAdmin() {
        const hasOrgs = !_.isEmpty(_.get(window.ya, 'connect.initial.organizations'));

        return !this.isInternal() && hasOrgs;
    }

    /**
     * Возвращает url страницы авторизации
     * @returns {String}
     */
    getAuthUrl() {
        return Url.build(ConfigStore.get('passport.session.login'), {
            retpath: location.href,
        });
    }

    /**
     * Возвращает url для выхода
     * @returns {String}
     */
    getLogoutUrl() {
        return Url.build(ConfigStore.get('passport.session.logout'), {
            uid: this.getUserId(),
            yu: cookie.get('yandexuid'),
            retpath: Url.getReturnPath() || Url.getLocation('/'),
        });
    }

    /**
     * Возвращает url для смены авторизованного пользователя
     * @param   {String|Number} id
     * @param   {String} [retpath]
     * @returns {String}
     */
    getSessionChangeUrl(id, retpath) {
        return Url.build(ConfigStore.get('passport.session.change'), {
            uid: id,
            yu: cookie.get('yandexuid'),
            retpath: retpath || Url.getReturnPath() || Url.getLocation('/'),
        });
    }

    /**
     * Возвращает url для добавления нового авторизованного пользователя
     * @param   {String} [retpath]
     * @returns {String}
     */
    getNewSessionUrl(retpath) {
        return Url.build(ConfigStore.get('passport.session.add'), {
            retpath: retpath || Url.getReturnPath() || Url.getLocation('/'),
        });
    }

    /**
     * Возвращает url страницы смены пароля
     * @returns {String}
     */
    getPasswordChangeUrl() {
        return Url.build(ConfigStore.get('passport.session.passwordChange'), {
            retpath: Url.getReturnPath() || Url.getLocation('/'),
        });
    }

    getViewMode() {
        return Url.getContext();
    }

    hasAvailableService(serviceId) {
        return _.get(window.ya, `connect.initial.services.${serviceId}.available`) !== false;
    }

    hasEnabledService(serviceId) {
        const service = this.getService(serviceId);

        return Boolean(service && service.ready);
    }

    getEnabledServices() {
        return this.getServices().filter(service => service.ready);
    }

    hasPaidServices() {
        let value = false;

        this.getEnabledServices().forEach(service => {
            value |= service.trial_expired;
        });

        return Boolean(value);
    }

    getServices() {
        const org = this.getOrganization();

        return org ? org.getServices() : [];
    }

    getService(serviceId) {
        return _.find(this.getServices(), { slug: serviceId });
    }

    isServiceReady(serviceId) {
        const service = this.getService(serviceId) || {};

        if (!service.enabled) {
            return true;
        }

        return typeof service.ready === 'boolean' ? service.ready : true;
    }

    getServiceTrialStatus(serviceId) {
        const service = this.getService(serviceId) || {};
        const { trial: trialData } = service;

        if (trialData && trialData.status === TRIAL_STATUS.INAPPLICABLE) {
            return trialData.status;
        }

        if (!trialData || !trialData.expiration_date) {
            return TRIAL_STATUS.NOT_STARTED;
        }

        return trialData.status;
    }

    isServiceEnabled(serviceId) {
        const serviceData = this.getService(serviceId) || {};

        // TODO: Убрать после того как директория починит баг [https://st.yandex-team.ru/DIR-4883]
        if (!serviceData.enabled) {
            return serviceData.enabled;
        }

        return this.isServiceReady(serviceId) ? serviceData.enabled : !serviceData.enabled;
    }

    hasDebt() {
        const org = this.getOrganization();

        if (org) {
            return org.hasDebt();
        }
    }

    hasOwnedDomains() {
        const org = this.getOrganization();

        if (org) {
            return org.hasOwnedDomains();
        }
        const orgId = _.get(window.ya, 'connect.initial.state.organization');

        return _.get(window.ya, `connect.initial.organizations.${orgId}.has_owned_domains`);
    }

    isIncompleteOrganization() {
        return !this.hasOwnedDomains() && !FeaturesStore.isYO();
    }

    isCaptchaRequired() {
        return _.get(window.ya, 'connect.initial.isCaptchaRequired');
    }
}

export default window.ya.connect.AuthStore = new AuthStore(dispatcher);
