/**
 * 消息、活动流程
 */

import moment = require("moment");
import { ACTIVITYSTATE, ACTIVITYTYPE, CHANGEAPPLYTYPE, CLIENTACTIVITYLABLE, CLIENTACTIVITYSTATE, CLIENTMSGLABLE, INFOCHANGEAPPLYTYPE, MAILTYPE, MEMBERLEVEL, MEMBERTYPE, STATE } from "../../config/enum";
import { ERRORENUM } from "../../config/errorEnum";
import { addManyData, addOneData } from "../../data/add";
import { TABLEENUM } from "../../data/models/model";
import { find, findCount, findOnce, findOnceToSort, findToPage, findToSort, findToSortToPage } from "../../data/select";
import { generateSystemId, getTodayMs, successErrorResult, successResult } from "../../tools/system";
import { BizError } from "../../util/bizError";
import { extractData } from "../../util/piecemeal";
import { changeEnumValue } from "../../util/verificationEnum";
import { updateManyData, updateOneData } from "../../data/update";
import { eccCityCode } from "../../config/cityConfig";
import { deleteOneData } from "../../data/delete";
import { systemSendMail } from "../mail";


/**
 * 消息列表
 * @param msgTitle 消息标题
 * @param effectiveStartTime 有效开始时间
 * @param effectiveEndTime 有效结束时间
 * @param pageNumber 当前页
 */
export async function getMessageList({msgTitle, effectiveStartTime, effectiveEndTime, pageNumber}) {
    let selectParam:any = {};
    if (msgTitle) selectParam.msgTitle = {"$regex":`${msgTitle}`};
    if (effectiveStartTime) {
        selectParam["effectiveTime"] = {"$gt":effectiveStartTime};
    }
    if (effectiveEndTime) {
        if (!selectParam["effectiveTime"]) selectParam["effectiveTime"] = {};
        selectParam["effectiveTime"]["$lt"] = effectiveEndTime;
    }

    const SelectFiles = ["msgId", "lableId", "msgTitle", "effectiveTime", "msgContent", "isPop"];
    let dbList = await findToSortToPage(TABLEENUM.消息通知表, selectParam, SelectFiles, {createTime:-1}, pageNumber);
    // let dbList = await findToPage(TABLEENUM.消息通知表, selectParam, SelectFiles, pageNumber);
    let dataCount = await findCount(TABLEENUM.消息通知表, selectParam);

    let dataList = [];
    for (let i = 0; i < dbList.length; i++) {
        let info = dbList[i];
        let item:any = extractData(info, SelectFiles);
        item.lableId = [];
        /**处理固定消息对象 */
        for (let lableId = 0; lableId < info.lableId.length; lableId++) {
            for (let key in CLIENTMSGLABLE) {
                let anyKey:any = key;
                if (isNaN(anyKey)) {
                    let value = CLIENTMSGLABLE[key];
                    if (info.lableId[lableId] == value) {
                        item.lableId.push(anyKey);
                    }
                }
            }
            
        }
        /**处理消息对象返回标签名称 */
        let lableInfo = await find(TABLEENUM.标签表, {lableId:{"$in":info.lableId}}, ["lableName"]);
        if (lableInfo) {
            lableInfo.forEach ( lableItem => {
                item.lableId.push(lableItem.lableName);
            });
        }
        
        item.effectiveTime = moment(item.effectiveTime).format("YYYY-MM-DD");
        dataList.push(item);
    }

    return {dataList, dataCount};
}


/**
 * 新建消息
 * @param userId 会员id（请求头id）
 * @param lableId 标签id（消息对象）
 * @param msgTitle 消息标题
 * @param effectiveTime 有效时间
 * @param msgContent 消息内容 
 */
export async function addMessage({userId, lableId, msgTitle, effectiveTime, msgContent}) {
    /**消息Id */
    const msgId = generateSystemId(TABLEENUM.消息通知表, userId);
    let addInfo = {
        msgId,
        lableId,
        msgTitle,
        createTime:new Date().valueOf(),
        effectiveTime,
        msgContent
    };
    await addOneData(TABLEENUM.消息通知表, addInfo);

    /**消息对象（标签id）对应的用户新建一条消息未读状态 */
    let selectParam = {};
    if(lableId.includes(CLIENTMSGLABLE.所有人)) {
        selectParam = {};
    } else if (lableId.includes(CLIENTMSGLABLE.个人会员)) {
        selectParam = {memberType:{"$in": MEMBERTYPE.个人会员}}
    } else if (lableId.includes(CLIENTMSGLABLE.单位会员)) {
        selectParam = {memberType:{"$in": MEMBERTYPE.单位会员}}
    } else if (lableId.includes(CLIENTMSGLABLE.理事)) {
        selectParam = {memberLever:{"$in": MEMBERLEVEL.理事会员}}
    } else if (lableId.includes(CLIENTMSGLABLE.常务理事)) {
        selectParam = {memberLever:{"$in": MEMBERLEVEL.常务理事会员}}
    } else {
        selectParam = {lableId:{"$in":lableId}}
    }

    let userInfo = await find(TABLEENUM.用户表, selectParam, ["userId"]);
    let addReadInfo = [];
    for (let i = 0; i < userInfo.length; i++) {
        /**消息已读Id */
        const readId = generateSystemId(TABLEENUM.消息已读状态表, userId);
        addReadInfo.push({
            readId,
            msgId,
            userId:userInfo[i].userId,
            isRead:STATE.否
        });
    }
    await addManyData(TABLEENUM.消息已读状态表, addReadInfo);

    return successResult();
}


/**
 * 修改消息
 * @param msgId 消息Id
 * @param form 修改消息表单
 * @param form.lableId 标签id（消息对象）
 * @param form.msgTitle 消息标题
 * @param form.effectiveTime 有效时间
 * @param form.msgContent 消息内容 
 */
export async function updateMessage({msgId, form}) {
    let msgInfo = await findOnce(TABLEENUM.消息通知表, {msgId}, ["msgId"]);
    if (!msgInfo || !msgInfo.msgId) throw new BizError(ERRORENUM.目标数据不存在);

    await updateOneData(TABLEENUM.消息通知表, {msgId}, form);

    return successResult();
}


/**
 * 修改是否弹窗
 * @param msgId 消息id 
 * @returns 
 */
export async function updateIsPop({msgId, isPop}) {
    let msgInfo = await findOnce(TABLEENUM.消息通知表, {msgId}, ["msgId", "isPop"]);
    if (!msgInfo || !msgInfo.msgId) throw new BizError(ERRORENUM.目标数据不存在);
    if (msgInfo.isPop == isPop) return;
    
    await updateOneData(TABLEENUM.消息通知表, {msgId}, {isPop});

    return successResult();
}


/**
 * 删除消息
 * @param msgId 消息Id
 * @returns 
 */
export async function delMessage({msgId}) {
    let msgInfo = await findOnce(TABLEENUM.消息通知表, {msgId}, ["msgId"]);
    if (!msgInfo || !msgInfo.msgId) throw new BizError(ERRORENUM.目标数据不存在);
    
    await deleteOneData(TABLEENUM.消息通知表, {msgId});
    return successResult();
}


/**
 * 游客消息通知
 * @param userId 会员Id（请求头id）
 * @returns 
 */
 export async function touristMessage() {
    let selectParam:any = {"$or":[{ lableId:{"$in":CLIENTMSGLABLE.所有人} }]};

    let dataList = [];
    const SelectFiles = ["msgId", "msgTitle", "effectiveTime", "msgContent", "isPop"];
    let msgInfo = await findToSort(TABLEENUM.消息通知表, selectParam, {createTime:-1}, SelectFiles);
    // if (!msgInfo || !msgInfo.msgId) throw new BizError(ERRORENUM.目标数据不存在);
    if (msgInfo) {
        msgInfo.forEach( info => {
            if (!info.msgId) return successErrorResult("暂无消息通知");
        });
    }
    
    for(let i = 0; i < msgInfo.length; i++) {
        let info = msgInfo[i];
        let item:any = extractData(info, SelectFiles);
        item.effectiveTime = moment(item.effectiveTime).format("YYYY-MM-DD");
        item.readId = "";
        item.isRead = 0;

        dataList.push(item);
    }
    
    return {dataList};
}


/**
 * 消息通知
 * @param userId 会员Id（请求头id）
 * @returns 
 */
export async function noticeMessage({userId}) {
    /**非游客用户通知消息条件 */
    let userInfo = await findOnce(TABLEENUM.用户表, {userId}, ["lableId", "memberType", "memberLever", "rejectRemarks", "changeApplyType", "rejectRemarks"]);
    if (!userInfo) throw new BizError(ERRORENUM.目标数据不存在);
    // if (!userInfo || !userInfo.lableId) return successErrorResult("该会员暂无消息通知标签分类");
    
    let nowDate = new Date().valueOf();
    let selectParam:any = {
        "$or":[{ lableId:{"$in":CLIENTMSGLABLE.所有人} }],
        effectiveTime:{"$gt":nowDate} //有效时间大于当前时间的消息发送通知
    };

    let memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);
    let memberLever = changeEnumValue(MEMBERLEVEL, userInfo.memberLever);
    selectParam["$or"].push(
        { 
            lableId:{"$in":memberType}
        },
        { 
            lableId:{"$in":memberLever}
        },
        {
            lableId:{"$in":userInfo.lableId},
            // effectiveTime:{"$gt":nowDate} //有效时间大于当前时间的消息发送通知
        }
    )
    
    let dataList = [];
    const SelectFiles = ["msgId", "msgTitle", "effectiveTime", "msgContent", "isPop", "lableId"];
    let msgList = await findToSort(TABLEENUM.消息通知表, selectParam, {createTime:-1}, SelectFiles);
    
    let msgReadList = await find(TABLEENUM.消息已读状态表, {userId:userId}, ["readId", "isRead", "msgId"]);
    let distinctMap = {};
    msgReadList.forEach(info => {
        let {msgId} = info;
        distinctMap[msgId] = info;
    });


    for(let i = 0; i < msgList.length; i++) {
        let info = msgList[i];
        let item:any = extractData(info, SelectFiles);
        item.effectiveTime = moment(item.effectiveTime).format("YYYY-MM-DD");

        //会员的消息已读数据
        /**没有已读状态的用户新建一条消息未读状态 */
        if (!distinctMap[info.msgId]) {
            const ReadId = generateSystemId(TABLEENUM.消息已读状态表, userId);
            let addReadInfo = {
                readId:ReadId,
                msgId:item.msgId,
                userId,
                isRead:STATE.否
            }
            await addOneData(TABLEENUM.消息已读状态表, addReadInfo);
            item.readId = ReadId;
            item.isRead = STATE.否;
        } else {
            item.readId = distinctMap[info.msgId].readId;
            item.isRead = distinctMap[info.msgId].isRead;
        }
        
        if (item.lableId.includes(CLIENTMSGLABLE.驳回理事申请) || item.lableId.includes(CLIENTMSGLABLE.驳回常务理事申请)) {
            item.rejectRemarks = userInfo.rejectRemarks;
        }

        dataList.push(item);
    }

    //需要审批消息
    if (userInfo.changeApplyType && userInfo.changeApplyType == CHANGEAPPLYTYPE.驳回修改) {
        let msgId = `${userInfo.userId}_zwsp`;
        let readId = `${userInfo.userId}_zwsp_readId`;
        if (!distinctMap[msgId]) {
            //创建新的弹窗
            let addReadInfo = {
                readId,
                msgId:msgId,
                userId,
                isRead:STATE.否
            }
            await addOneData(TABLEENUM.消息已读状态表, addReadInfo);
            dataList.push(addReadInfo);
        } else {
            dataList.push({
                msgId,
                readId,
                userId,
                isRead:distinctMap[msgId].isRead
            });
        }
    } else {
        //把老消息去掉
        let msgId = `${userInfo.userId}_zwsp`;
        if (distinctMap[msgId]) { 
            await deleteOneData(TABLEENUM.消息已读状态表, {msgId} );
        }
    }

    let infomationHistory = await findOnceToSort(TABLEENUM.资料变更审批历史表, {userId}, {createTimeMs:-1});
    if (infomationHistory == INFOCHANGEAPPLYTYPE.驳回修改) {
        let msgId = `${userInfo.userId}_zlsp`;
        let readId = `${userInfo.userId}_zlsp_readId`;
        if (!distinctMap[msgId]) {
            //创建新的弹窗
            let addReadInfo = {
                readId,
                msgId:msgId,
                userId,
                isRead:STATE.否
            }
            await addOneData(TABLEENUM.消息已读状态表, addReadInfo);
            dataList.push(addReadInfo);
        } else {
            dataList.push({
                msgId,
                readId,
                userId,
                isRead:distinctMap[msgId].isRead
            });
        }
    } else {
         //把老消息去掉
         let msgId = `${userInfo.userId}_zlsp`;
         if (distinctMap[msgId]) { 
             await deleteOneData(TABLEENUM.消息已读状态表, {msgId} );
         }
    }


    
    return {dataList};
}


/**
 * 全部已读
 * @param userId 会员Id 
 */
export async function allMsgRead({userId}) {
    await updateManyData(TABLEENUM.消息已读状态表, {userId}, {isRead:STATE.是, readTime:new Date().valueOf()});

    return successResult();
}


/**
 * 修改消息为已读
 * @param readId 
 */
export async function updateMsgRead({readId}) {
    let msgReadInfo = await findOnce(TABLEENUM.消息已读状态表, {readId}, ["readId", "isRead"]);
    if (!msgReadInfo || !msgReadInfo.readId) throw new BizError(ERRORENUM.目标数据不存在);
    if (msgReadInfo.isRead == STATE.是) return;
    
    await updateOneData(TABLEENUM.消息已读状态表, {readId}, {readTime:new Date().valueOf(), isRead: STATE.是});

    return successResult();
}



/**
 * 活动通知列表
 * @param  activityName 活动名称
 * @param  activityStartTime 活动开始时间
 * @param  activityEndTime 活动结束时间
 * @param  pageNumber 当前页
 * @returns 
 */
export async function getActivityList({activityName, activityStartTime, activityEndTime, pageNumber}) {
    let selectParam:any = {};
    if (activityName) selectParam.activityName = {"$regex":`${activityName}`};
    /**活动时间完全在查询时间段内 gt:大于、lt:小于 */
    if (activityStartTime && activityEndTime) {
        selectParam["activityStartTime"] = { "$lte": activityEndTime },  
        selectParam["activityEndTime"] = { "$gte": activityStartTime } 
    }
    // if (activityStartTime) {
    //     selectParam["activityStartTime"] = {"$gt":activityStartTime};
    // }
    // if (activityEndTime) {
    //     if (!selectParam["activityEndTime"]) selectParam["activityEndTime"] = {};
    //     selectParam["activityEndTime"]["$lt"] = activityEndTime;
    // }

    const SelectFiles = ["activityId", "activityName", "activityType", "activityStartTime", "activityEndTime", "activityAdd", "enrollStartTime", "enrollEndTime", "lableId", "isTopUp"];
    let dbList = await findToSortToPage(TABLEENUM.活动通知表, selectParam, SelectFiles, {createTime:-1}, pageNumber);
    let dataCount = await findCount(TABLEENUM.活动通知表, selectParam);

    let dataList = [];
    for (let i = 0; i < dbList.length; i++) {
        let info = dbList[i];
        let item:any = extractData(info, SelectFiles);
        item.lableId = [];
        /**处理固定消息对象 */
        for (let lableId = 0; lableId < info.lableId.length; lableId++) {
            for (let key in CLIENTACTIVITYLABLE) {
                let anyKey:any = key;
                if (isNaN(anyKey)) {
                    let value = CLIENTACTIVITYLABLE[key];
                    if (info.lableId[lableId] == value) {
                        item.lableId.push(anyKey);
                    }
                }
            }
            
        }
        /**处理消息对象返回标签名称 */
        let lableInfo = await find(TABLEENUM.标签表, {lableId:{"$in":info.lableId}}, ["lableName"]);
        if (lableInfo) {
            lableInfo.forEach ( lableItem => {
                item.lableId.push(lableItem.lableName);
            });
        }
        
        /**枚举值、时间格式转换 */
        item.activityType = changeEnumValue(ACTIVITYTYPE, info.activityType);
        if (item.activityStartTime) item.activityStartTime = moment(item.activityStartTime).format("YYYY-MM-DD");
        if (item.activityEndTime) item.activityEndTime = moment(item.activityEndTime).format("YYYY-MM-DD");
        item.enrollStartTime = moment(item.enrollStartTime).format("YYYY-MM-DD");
        item.enrollEndTime = moment(item.enrollEndTime).format("YYYY-MM-DD");

        dataList.push(item);
    }

    return {dataList, dataCount};
}


/**
 * 新建活动
 * @param userId 会员id（请求头id）
 * @param form 新建活动表单 activityType, activityName, enrollForm, activityAdd, activityTime, lableId, enrollTime, activityContent
 * @returns 
 */
export async function addActivity({userId, form}) {
    /**消息Id */
    const activityId = generateSystemId(TABLEENUM.活动通知表, userId);
    
    let addInfo = form;
    addInfo.activityId = activityId;
    addInfo.createTime = new Date().valueOf();

    await addOneData(TABLEENUM.活动通知表, addInfo);

    /**消息对象（标签id）对应的用户新建一条消息未读状态 */
    let selectParam = {};
    if(form.lableId.includes(CLIENTMSGLABLE.所有人)) {
        selectParam = {};
    } else if (form.lableId.includes(CLIENTMSGLABLE.个人会员)) {
        selectParam = {memberType:{"$in": MEMBERTYPE.个人会员}}
    } else if (form.lableId.includes(CLIENTMSGLABLE.单位会员)) {
        selectParam = {memberType:{"$in": MEMBERTYPE.单位会员}}
    } else if (form.lableId.includes(CLIENTMSGLABLE.理事)) {
        selectParam = {memberLever:{"$in": MEMBERLEVEL.理事会员}}
    } else if (form.lableId.includes(CLIENTMSGLABLE.常务理事)) {
        selectParam = {memberLever:{"$in": MEMBERLEVEL.常务理事会员}}
    } else {
        selectParam = {lableId:{"$in":form.lableId}}
    }
    let userInfo = await find(TABLEENUM.用户表, selectParam, ["userId"]);
    let addReadInfo = [];
    for (let i = 0; i < userInfo.length; i++) {
        /**活动已读Id */
        const arId = generateSystemId(TABLEENUM.活动通知已读状态表, userId);
        addReadInfo.push({
            arId,
            activityId,
            userId:userInfo[i].userId,
            isRead:STATE.否
        });

         //发送邮件
        await systemSendMail(userInfo.userId, MAILTYPE.会员活动or会议通知 );
    }
    await addManyData(TABLEENUM.活动通知已读状态表, addReadInfo);

  

    return successResult();
}


/**
 * 修改活动为已读
 * @param readId 
 */
export async function updateActivityRead({arId}) {
    let activityReadInfo = await findOnce(TABLEENUM.活动通知已读状态表, {arId}, ["arId", "isRead"]);
    if (!activityReadInfo || !activityReadInfo.arId) throw new BizError(ERRORENUM.目标数据不存在);
    if (activityReadInfo.isRead == STATE.是) return;
    
    await updateOneData(TABLEENUM.活动通知已读状态表, {arId}, {readTime:new Date().valueOf(), isRead: STATE.是});

    return successResult();
}


/**
 * 获取活动详细-修改回显
 * @param param0 
 * @returns 
 */
export async function getActivityDetailed({activityId}) {
    let SelectFiles = ["activityId", "activityType", "activityName", "enrollForm", "activityAdd", "activityStartTime", "activityEndTime", "enrollStartTime", "enrollEndTime", "activityContent", "lableId"];
    
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, SelectFiles);
    if (!activityInfo) throw new BizError(ERRORENUM.目标数据不存在);

    let dataList:any = extractData(activityInfo, SelectFiles);
    if (dataList.activityStartTime) dataList.activityStartTime = moment(dataList.activityStartTime).format("YYYY-MM-DD");
    if (dataList.activityEndTime) dataList.activityEndTime = moment(dataList.activityEndTime).format("YYYY-MM-DD");
    dataList.enrollStartTime = moment(dataList.enrollStartTime).format("YYYY-MM-DD");
    dataList.enrollEndTime = moment(dataList.enrollEndTime).format("YYYY-MM-DD");

    return {dataList};
}


/**
 * 修改活动
 * @param activityId 活动id 
 * @param form 新建活动表单 activityType, activityName, enrollForm, activityAdd, activityStartTime, activityEndTime, lableId, enrollStartTime, enrollEndTime, activityContent
 * @returns 
 */
export async function updateActivity({activityId, form}) {
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, ["activityId"]);
    if (!activityInfo || !activityInfo.activityId) throw new BizError(ERRORENUM.目标数据不存在);

    if (activityInfo.activityType == ACTIVITYTYPE.线下活动) {
        if (!form.activityStartTime || !form.activityEndTime) throw new BizError(ERRORENUM.线下活动的活动时间必填);
    }

    await updateOneData(TABLEENUM.活动通知表, {activityId}, form);

    return successResult();
}


/**
 * 删除活动
 * @param activityId 活动id 
 * @returns 
 */
export async function delActivity({activityId}) {
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, ["activityId"]);
    if (!activityInfo || !activityInfo.activityId) throw new BizError(ERRORENUM.目标数据不存在);
    
    await deleteOneData(TABLEENUM.活动通知表, {activityId});
    return successResult();
}


/**
 * 修改是否置顶
 * @param activityId 活动id 
 * @returns 
 */
export async function updateIsTopUp({activityId, isTopUp}) {
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, ["activityId", "isTopUp"]);
    if (!activityInfo || !activityInfo.activityId) throw new BizError(ERRORENUM.目标数据不存在);
    if (activityInfo.isTopUp == isTopUp) return;
    
    await updateOneData(TABLEENUM.活动通知表, {activityId}, {isTopUp});

    return successResult();
}


/**
 * 活动报名人员列表
 * @param activityId 活动Id
 */
export async function enrollList({activityId}) {
    let activityInfo = await find(TABLEENUM.活动报名表, {activityId}, ["userId"]);
    const SelectFiles = ["userId", "name", "unitName", "memberType", "memberLevel", "phone"];
    const DataFiles = ["userId", "name", "memberType", "memberLevel", "phone"];
    let dataList = [];
    for (let i = 0; i < activityInfo.length; i++) {
        let info = activityInfo[i];
        let userInfo = await findOnce(TABLEENUM.用户表, {userId:info.userId}, SelectFiles);
        let item:any = extractData(userInfo, DataFiles);
        if (userInfo.memberType == MEMBERTYPE.单位会员) {
            item.name = userInfo.unitName;
        }
        if (!item.memberLevel) item.memberLevel = "未选择";
        else item.memberLevel = changeEnumValue(MEMBERLEVEL, item.memberLevel);
        item.memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);

        dataList.push(item);
    }

    return {dataList};
}


/**
 * 根据选择的会员下载报名表
 * @param id 会员Id
 */
export async function getEnrollUrl({id, activityId}) {
    let activityData = [];
    for (let i = 0; i < id.length; i++) {
        let activityInfo = await findOnce(TABLEENUM.活动报名表, {userId:id[i], activityId}, ["userId", "activityId", "enrollUrl"]);
        if (!activityInfo) throw new BizError(ERRORENUM.目标数据不存在);
        
        let item:any = extractData(activityInfo, ["userId", "activityId", "enrollUrl"]);
        let userInfo = await findOnce(TABLEENUM.用户表, {userId:activityInfo.userId}, ["userName", "name", "memberType"]);
        if (userInfo.memberType == MEMBERTYPE.个人会员) item.name = userInfo.name
        else item.name = userInfo.userName
        item.memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);
        
        activityData.push(item);
    }

    return {activityData};
}



//个人页------------------------------------
/**
 * 获取活动对应报名表模板
 * @param activityId 活动id 
 * @returns 
 */
export async function activityEnrollForm({activityId}) {
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, ["enrollForm"]);
    if (!activityInfo || !activityInfo.enrollForm) throw new BizError(ERRORENUM.目标数据不存在);

    return {enrollForm:activityInfo.enrollForm};
}


/**
 * 申请报名表
 * @param userId 会员Id（请求头id）
 * @param activityId 活动id 
 * @param enrollUrl 已填报报名表地址
 */
export async function activityEnroll({userId, activityId, enrollUrl}) {
    let userInfo = await findOnce(TABLEENUM.用户表, {userId}, ["lableId", "memberType", "memberLevel"]);
    if (!userInfo || !userInfo.lableId) throw new BizError(ERRORENUM.目标数据不存在);

    let selectParam = {
        activityId,
        "$or":[
            {
                lableId:{"$in":userInfo.lableId},
            }
        ]
    };
    let memberType = "";
    let memberLevel = "";
    if (userInfo.memberType) {
        memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);
        selectParam["$or"].push({ lableId:{"$in":memberType} });
    }
    if (userInfo.memberLevel) {
        memberLevel = changeEnumValue(MEMBERLEVEL, userInfo.memberLevel);
        selectParam["$or"].push({ lableId:{"$in":memberLevel} });
    }

    let activityInfo = await find(TABLEENUM.活动通知表, selectParam, ["lableId"]);
    if (activityInfo) {
        activityInfo.forEach( info => {
            if (!info.lableId) {
                return successErrorResult("用户没有在此活动对象范围内");
                // throw new BizError(ERRORENUM.用户没有在此活动对象内, "用户没有在此活动对象范围内");
            }
        })
    }

    let activityEnroll = await findOnce(TABLEENUM.活动报名表, {userId, activityId});
    if (activityEnroll) return successErrorResult("已参加该活动，不能重复报名");

    /**消息Id */
    const enrollId = generateSystemId(TABLEENUM.活动报名表, userId);
    
    let addInfo = {
        enrollId,
        userId,
        activityId,
        enrollUrl
    }

    await addOneData(TABLEENUM.活动报名表, addInfo);
    // await updateOneData(TABLEENUM.活动通知表, {activityId}, {activityState:ACTIVITYSTATE.已参加});

    return successResult();
}

/**
 * 会员个人页-查看活动
 * 根据登录的用户id查询标签id，获取活动通知里对应标签id的所有活动
 * @param userId 会员Id（请求头id）
 */
export async function seeActivity({userId}) {
    let userInfo = await findOnce(TABLEENUM.用户表, {userId}, ["lableId", "memberType", "memberLevel"]);
    if (!userInfo || !userInfo.lableId) throw new BizError(ERRORENUM.目标数据不存在);

    let selectParam = {
        "$or":[
            {
                lableId:{"$in":userInfo.lableId},
            }
        ],
        activityState:{"$nin":ACTIVITYSTATE.已结束}
    };
    let memberType = "";
    let memberLevel = "";
    if (userInfo.memberType) {
        memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);
        selectParam["$or"].push({ lableId:{"$in":memberType} });
    }
    if (userInfo.memberLevel) {
        memberLevel = changeEnumValue(MEMBERLEVEL, userInfo.memberLevel);
        selectParam["$or"].push({ lableId:{"$in":memberLevel} });
    }

    let SelectFiles = ["activityId", "activityName", "activityStartTime", "activityEndTime"];
    // let activityInfo = await find(TABLEENUM.活动通知表, selectParam, SelectFiles);
    let activityInfo = await findToSort(TABLEENUM.活动通知表, selectParam, {createTime:-1}, SelectFiles);
    // if (!activityInfo || !activityInfo.length) throw new BizError(ERRORENUM.目标数据不存在);

    let dataList = [];
    if (activityInfo) {
        for (let i  = 0; i < activityInfo.length; i++) {
            let info = activityInfo[i];
            let item:any = extractData(info, SelectFiles);
            // item.activityStartTime = moment(item.activityStartTime).format("YYYY-MM-DD");
            // item.activityEndTime = moment(item.activityEndTime).format("YYYY-MM-DD");
            if (item.activityStartTime) item.activityStartTime = moment(item.activityStartTime).format("YYYY-MM-DD");
            if (item.activityEndTime) item.activityEndTime = moment(item.activityEndTime).format("YYYY-MM-DD");

            //会员的消息已读数据
            let selectActivityParam:any = {activityId:item.activityId, userId:userId};
            // if (!userId) selectMsgParam.userId = userId;
            let readOldInfo = await findOnce(TABLEENUM.活动通知已读状态表, selectActivityParam, ["arId", "isRead"]);
            let readInfo:any = {};

            /**没有已读状态的用户新建一条活动未读状态 */
            if (!readOldInfo) {
                /**活动已读Id */
                const arId = generateSystemId(TABLEENUM.活动通知已读状态表, userId);
                let addReadInfo = {
                    arId,
                    activityId:item.activityId,
                    userId,
                    isRead:STATE.否
                }
                await addOneData(TABLEENUM.活动通知已读状态表, addReadInfo);
                
                readInfo = await findOnce(TABLEENUM.活动通知已读状态表, selectActivityParam, ["arId", "isRead"]);
            } else {
                readInfo = readOldInfo;
            }
            item.arId = readInfo.arId;
            item.isRead = readInfo.isRead;

            dataList.push(item);
        }
    }
    
    return {dataList};
}


/**
 * 会员个人页-查看更多活动列表
 * @param userId 会员Id（请求头id）
 * @param param0 
 */
export async function homeActivityList({userId, activityState, pageNumber}) {
    let userInfo = await findOnce(TABLEENUM.用户表, {userId}, ["lableId", "memberType", "memberLevel"]);
    if (!userInfo || !userInfo.lableId) throw new BizError(ERRORENUM.目标数据不存在);
    
    let selectParam:any = {
        "$or":[
            {
                lableId:{"$in":userInfo.lableId},
            }
        ]
    };
    let memberType = "";
    let memberLevel = "";
    if (userInfo.memberType) {
        memberType = changeEnumValue(MEMBERTYPE, userInfo.memberType);
        selectParam["$or"].push({ lableId:{"$in":memberType} });
    }
    if (userInfo.memberLevel) {
        memberLevel = changeEnumValue(MEMBERLEVEL, userInfo.memberLevel);
        selectParam["$or"].push({ lableId:{"$in":memberLevel} });
    }

    if (activityState == ACTIVITYSTATE.已结束) selectParam.activityState = activityState;

    if (activityState == CLIENTACTIVITYSTATE.已参加) {
        selectParam.activityId = [];
        let activityInfo = await find(TABLEENUM.活动报名表, {userId}, ["activityId"]);
        activityInfo.forEach( info => {
            selectParam.activityId.push(info.activityId);
        })
    }

    let SelectFiles = ["activityId", "activityName", "activityStartTime", "activityEndTime"];
    // let activityInfo = await find(TABLEENUM.活动通知表, selectParam, SelectFiles);
    
    let activityInfo = await findToSortToPage(TABLEENUM.活动通知表, selectParam, SelectFiles, {activityStartTime:-1}, pageNumber);
    let dataCount = await findCount(TABLEENUM.活动通知表, selectParam);

    let dataList = [];
    if (activityInfo) {
        activityInfo.forEach( info => {
            let item:any = extractData(info, SelectFiles);
            // item.activityStartTime = moment(item.activityStartTime).format("YYYY-MM-DD");
            // item.activityEndTime = moment(item.activityEndTime).format("YYYY-MM-DD");
            if (item.activityStartTime) item.activityStartTime = moment(item.activityStartTime).format("YYYY-MM-DD");
            if (item.activityEndTime) item.activityEndTime = moment(item.activityEndTime).format("YYYY-MM-DD");
            dataList.push(item);
        });
    }

    return {dataList, dataCount};
}


/**
 * 会员个人页-查看更多活动详细
 * @param activityId 
 * @returns 
 */
export async function homeActivityDetailed({activityId}) {
    let SelectFiles = ["activityId", "activityName", "activityStartTime", "activityEndTime", "enrollStartTime", "enrollEndTime", "activityAdd", "activityContent"];
    
    let activityInfo = await findOnce(TABLEENUM.活动通知表, {activityId}, SelectFiles);
    if (!activityInfo) throw new BizError(ERRORENUM.目标数据不存在);

    let dataList:any = extractData(activityInfo, SelectFiles);
    if (dataList.activityStartTime) dataList.activityStartTime = moment(dataList.activityStartTime).format("YYYY-MM-DD");
    if (dataList.activityEndTime) dataList.activityEndTime = moment(dataList.activityEndTime).format("YYYY-MM-DD");
    dataList.enrollStartTime = moment(dataList.enrollStartTime).format("YYYY-MM-DD");
    dataList.enrollEndTime = moment(dataList.enrollEndTime).format("YYYY-MM-DD");

    return {dataList};
}



// -------------------------
/**
 * 活动状态切换
 * 设置定时器，每一小时检查一次活动状态
 */
export async function initActivity() {
    updateActivityState();
    setInterval(async function () {
        await updateActivityState();
    }, 3600 * 1000);
}


/**
 * 修改活动状态
 * @returns 
 */
export async function updateActivityState() {
    let time = getTodayMs();
    let activityInfo = await find(TABLEENUM.活动通知表, {activityState:ACTIVITYSTATE.已开始});
    if (!activityInfo || !activityInfo.length) return;

    let formParam = {activityState:ACTIVITYSTATE.已结束};

    for (let i = 0; i < activityInfo.length; i++) {
        let info = activityInfo[i];
        if (info.activityType == ACTIVITYTYPE.线上活动) {
            if (time > info.enrollEndTime) {
                await updateOneData(TABLEENUM.活动通知表, {activityId:info.activityId}, formParam);
            }
        }
        
        if (info.activityType == ACTIVITYTYPE.线下活动) {
            if (time > info.activityEndTime) {
                await updateOneData(TABLEENUM.活动通知表, {activityId:info.activityId}, formParam);
            }
        }

    }

}


