/**
 * 用户逻辑
 */

import { ADMINTYPE, CODETYPE, MEMBERSTATE, STATE, USERREGISTERSTATE } from "../../config/enum";
import { ERRORENUM } from "../../config/errorEnum";
import { addOneData } from "../../data/add";
import { TABLEENUM } from "../../data/models/model";
import { findCount, findOnce, findOnceToSort } from "../../data/select";
import { updateOneData } from "../../data/update";
import { generateSMSCode, generateToken, getTodayMs, successResult } from "../../tools/system";
import { BizError } from "../../util/bizError";
import { changeEnumValue } from "../../util/verificationEnum";
import { sendALSMS } from "../sms";



/**
 * 登陆
 * @param param0 
 * @returns 
 */
export async function login({loginId, pwd}) {
    let selectParam = { "$or":[{loginId:loginId}, {phone:loginId}] };
    let userInfo = await findOnce(TABLEENUM.用户表, selectParam);
    
    if (!userInfo || !userInfo.userId) throw new BizError(ERRORENUM.账号或密码错误);

    if (userInfo.isBlackUser == STATE.是) throw new BizError(ERRORENUM.黑名单用户不允许登录, "您的会员服务已过期，如需恢复请联系秘书处：010-86208681");

    if (userInfo.isInput && !userInfo.inputUserChangePwd) {
        return {
            isInput:userInfo.isInput,
            phone:userInfo.phone
        }
    }

    if (userInfo.pwd != pwd ) throw new BizError(ERRORENUM.账号或密码错误);

    let token = "";
    const Now = new Date().valueOf();
    token = generateToken(userInfo.userId);
    await updateOneData(TABLEENUM.用户表, {userId:userInfo.userId}, {token, tokenMs:Now, lastLoginMs:Now});

    if (userInfo.memberState >= MEMBERSTATE.冻结 ) {
        throw new BizError(ERRORENUM.该账号已被冻结);
    }

    let dataInfo = {
        isAdmin:userInfo.isAdmin == STATE.是,
        name:userInfo.isAdmin ? changeEnumValue(ADMINTYPE, userInfo.adminType ) : userInfo.name,
        userId:userInfo.userId,
        token:token,
        adminLv:userInfo.adminLv,
        timeMs:Now,
        isPass:userInfo.userRegisterState == USERREGISTERSTATE.通过,
        memberType:userInfo.memberType,
        isInput:(userInfo.isInput && !userInfo.inputUserChangePwd),
        phone:userInfo.phone
    };

    return {dataInfo};
}


/**
 * 退出登陆
 * @param userId 
 * @returns 
 */
export async function logout({userId}) {
    let token = generateToken(userId);
    await updateOneData(TABLEENUM.用户表, {userId:userId}, {token});

    return successResult();
}


/**
 * 修改密码
 * @param param0 
 * @returns 
 */
export async function changePwd({phone, pwd, confirmation, code}) {
    if (pwd.search(/^[A-Za-z0-9]{6,18}$/) < 0) throw new BizError(ERRORENUM.密码只能由6至18位字符和数字组成);
    if (pwd != confirmation)  throw new BizError(ERRORENUM.两次密码不一致);

    let codeInfo = await findOnce(TABLEENUM.验证码表, {codeNum:code, phone, type:CODETYPE.修改密码, isUse:false});
    if (!codeInfo || !codeInfo.codeNum) {
        throw new BizError(ERRORENUM.验证码错误);
    }

    let userInfo = await findOnce(TABLEENUM.用户表, {phone}, ["userId", "isInput", "inputUserChangePwd"]);
    if (!userInfo || !userInfo.userId) throw new BizError(ERRORENUM.手机号不正确);
    // let pwdStr = generatePwd(userInfo.userId, pwd); todo
    let pwdStr = pwd;
    let updateInfo:any = {pwd:pwdStr};
    if (userInfo.isInput && !userInfo.inputUserChangePwd) {
        updateInfo.inputUserChangePwd = true;
    }

    await updateOneData(TABLEENUM.用户表, {userId:userInfo.userId}, updateInfo);
    await updateOneData(TABLEENUM.验证码表, {codeNum:code, phone, type:CODETYPE.修改密码, isUse:false}, {isUse:true});

    return successResult();
}


/**
 * 修改密码【短信验证码】 success
 * @param userId 
 * @param phone 
 * @returns 
 */
export async function memberChangePwdSendCode({phone}) {
    let userInfo = await findOnce(TABLEENUM.用户表, {phone}, ["userId"]);
    if (!userInfo || !userInfo.userId) throw new BizError(ERRORENUM.不存在该手机号的账号);
    const NowMs = new Date().valueOf();
    let codeSelectParam = { phone, isUse:false,  type:CODETYPE.修改密码, sendMs:{"$gt":getTodayMs()} }
    let lastCodeInfo = await findOnceToSort(TABLEENUM.验证码表, codeSelectParam, {sendMs:-1});

    if (lastCodeInfo && lastCodeInfo.codeNum) {
        if ( (lastCodeInfo.sendMs + (60*1000)) > NowMs ) throw new BizError(ERRORENUM.频繁操作请稍后再试);
        /**校验今日同类型验证码次数 */
        let todayNotUseCount = await findCount(TABLEENUM.验证码表, codeSelectParam);
        if (todayNotUseCount >= 4) throw new BizError(ERRORENUM.发送验证码次数超限制, `${phone} 注册验证码超过限制3`);
    }

    const Code = generateSMSCode();//生成短信验证码

    /**发送短信模块 */
    await sendALSMS(Code, phone);
    let addInfo = {codeNum:Code, phone, sendMs:NowMs, type:CODETYPE.修改密码, isUse:false};
    await addOneData(TABLEENUM.验证码表, addInfo);

    return {code:""};
}


