/**
 * 后台管理员数据模型
 *
 * @author CaiAoLin
 * @date 2017/6/1
 * @version
 */
import mongoose from "mongoose";
import BaseModel from "../../common/base/base_model";
import crypto from "crypto";
import Request from "request";

class ManagerModel extends BaseModel {

    /**
     * 超级用户用户名
     *
     * @var {String}
     */
    adminUsername = 'admin';

    /**
     * 用户权限
     *
     * @var
     */
    permission = {
        'user': '用户管理',
        'notify': '通知管理',
        'stdBillsmain': '清单规则编辑器',
        'rationRepository': '定额编辑器',
        'report': '报表模板',
    };

    /**
     * 构造函数
     *
     * @return {void}
     */
    constructor() {
        let parent = super();
        parent.model = mongoose.model('manager');
        parent.init();
    }

    /**
     * 设置场景
     *
     * @param {string} scene
     * @return {void}
     */
    setScene(scene = '') {
        switch (scene) {
            // 更改密码验证规则
            case 'changePassword':
                this.model.schema.path('password').required(true);
                break;
            // CLD新增
            case 'cldInsert':
                this.model.schema.path('username').required(true);
                this.model.schema.path('create_time').required(true);
                this.model.schema.path('office').required(true);
                break;
        }
    }

    /**
     * 获取过滤条件
     *
     * @return {Object}
     */
    getFilterCondition(request) {
        let condition = {};
        let office = request.query.office;
        if (office !== '' && office !== undefined) {
            condition.office = parseInt(office);
        }

        let permission = request.query.permission;
        if (permission !== undefined) {
            // 0 ：权限为空的情况
            condition.permission = permission === '0' ? '' : permission;
        }

        return condition;
    }

    /**
     * 获取按创建时间倒序列表
     *
     * @param {object} condition
     * @param {number} page
     * @return {Promise}
     */
    getList(condition = null, page = 1) {
        page = parseInt(page);
        page = page <= 1 ? 1 : page;
        let option = {page: page, sort: {create_time:-1}};
        return this.db.find(condition, null, option);
    }

    /**
     * 用户密码加密
     *
     * @param {string} token
     * @param {string} password
     * @return {string}
     */
    encryptPassword(token, password) {
        let encryptPassword = crypto.createHmac('sha1', token).update(password)
            .digest().toString('base64');
        return encryptPassword;
    }

    /**
     * 更改密码
     *
     * @param {string} username
     * @param {string} password
     * @param {string} newPassword
     * @throws {string}
     * @return {Promise}
     */
    async changePassword(username, password, newPassword) {

        // 查找对应用户
        let managerData = await this.findDataByCondition({username: username});
        if (managerData.length <= 0) {
            return false;
        }

        // 验证旧密码
        let encryptPassword = this.encryptPassword(managerData.token, password);
        if (encryptPassword !== managerData.password) {
            throw '用户名或密码错误';
        }

        // 加密新密码
        let encryptNewPassword = this.encryptPassword(managerData.token, newPassword);
        let result = await this.db.update({username: username}, {password: encryptNewPassword});

        return result.ok === 1;
    }

    /**
     * 登录信息校验
     *
     * @param {String} username
     * @param {String} password
     * @return {Promise}
     */
    async validLogin(username, password) {
        let managerData = await this.findDataByCondition({username: username});

        // 没有找到对应数据
        /*if (managerData === null || managerData._id === undefined) {
            throw {code: 44001, err: '用户名或密码错误'};
        }*/

        // 是否禁止登录
        if (managerData && managerData.can_login !== 1) {
            throw {code: 44002, err: '用户名不存在'};
        }

        // 如果不是超级管理员登录则走CLD接口登录流程
        if (managerData === null || managerData._id === undefined || username !== this.adminUsername) {
            let CLDLoginInfo = await this.CLDLogin(username, password, managerData);
            if (CLDLoginInfo.can_login !== 1) {
                throw {code: 44002, err: '账号被停用'};
            }
            managerData = CLDLoginInfo;
        } else {
            // 加密密码
            let encryptPassword = this.encryptPassword(managerData.token, password);
            if (encryptPassword !== managerData.password) {
                throw {code: 44001, err: '用户名或密码错误'};
            }
        }

        return managerData;
    }


    /**
     * CLD登录
     *
     * @param {String} username
     * @param {String} password
     * @param {Object} managerData
     * @return {Promise}
     */
    async CLDLogin(username, password, managerData) {
        let result = managerData;
        if (username === '' || password === '') {
            throw {code: 44001, err: '用户名或密码错误'};
        }

        let CLDUrl = 'http://cld.smartcost.com.cn/api/auth';
        // 生成加密token
        let [encryptToken, postTime] = this.generateCLDToken();
        let postData = {
            username: username,
            password: password,
            time: postTime,
            token: encryptToken,
            app: 'scConstruct'
        };

        let postOption = {
            url: CLDUrl,
            form: postData,
            encoding: 'utf8'
        };
        let responseData = await this.CLDRequest(postOption);
        // 登录成功后，存在此用户则直接返回
        if (managerData) {
            return result;
        }

        // 不存在则新增
        this.setScene('cldInsert');
        let current = new Date().getTime();
        //cld账号登录的统一设置可以看到用户管理和允许登录
        let insertData = {
            username: username,
            password: '',
            token: '',
            create_time: current,
            last_login: current,
            office: responseData.office,
            position: responseData.position,
            permission: '',
            can_login: 0
        };
        result = this.db.create(insertData);

        return result;
    }

    /**
     * CLD请求
     *
     * @param {Object} postOption
     * @return {Promise}
     */
    CLDRequest(postOption) {
        return new Promise(function(resolve, reject) {
            // 发起请求
            Request.post(postOption, function(error, response, body) {
                console.log(`body`);
                console.log(body);
                if (error || response.statusCode !== 200) {
                    console.log(response.statusCode + ':' + error);
                    reject({code: 44002, err: '接口请求出错'});
                    return;
                }

                body = JSON.parse(body);

                // 如果接口返回错误
                if (body.err !== 0) {
                    reject({code: body.err, err: '接口返回错误'});
                    return;
                }

                resolve(body.data);
            });
        });
    }

    /**
     * 生成CLD Token
     *
     * @return {Array}
     */
    generateCLDToken() {
        // 加密内容
        let token = 'sc@ConS!tru@ct*88';
        let currentTime = new Date().getTime();
        currentTime = parseFloat(currentTime / 1000).toFixed(0);

        let encryptToken = this.encryptPassword(token, (token + currentTime));

        return [encryptToken, currentTime];
    }

    /**
     * 新增管理员
     *
     * @param {Object} data
     * @return {Promise}
     */
    async createManager(data) {
        if (Object.keys(data).length <= 0) {
            throw '数据格式错误';
        }
        let result = await this.db.create(data);

        return result;
    }

    /**
     * 删除后台用户权限
     * @param permission
     * @return {Promise.<void>}
     */
    async updateByPermission(permission) {
        let result = await this.db.update({permission: permission}, {permission: ''});

        return result.ok === 1;
    }

}

export default ManagerModel;
