import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { genCode } from '../pubUtils/util';
import { getZeroPointD } from '../pubUtils/timeUtil';
import { SHOP_REFRESH_TYPE } from '../consts';

/**
  * 玩家购买商店记录表，每个商品一条，每次刷新新建一条
**/
@modelOptions({ schemaOptions: { id: false } })
@index({ roleId: 1, shop: 1, type: 1 })

export default class UserShop extends BaseModel {
    @prop({ required: true })
    code: string;					// 该记录唯一标识

    @prop({ required: true })
    roleId: string;					// 玩家id

    @prop({ required: true })
    roleName: string;				// 玩家名

    @prop({ required: true })
    activityId: number; 				// 商店id

    @prop({ required: true })
    shop: number; 				// 商店id

    @prop({ required: true })
    type: number; 				// 商店页签id

    @prop({ required: true })
    itemId: number; 				// 商品id

    @prop({ required: true })
    createTime: number; 			// 商品上新时间

    @prop({ required: true })
    goodId: number; 				// 商品包含的物品id

    @prop({ required: true })
    refreshType: number; 			// 商品刷新类型 1-每日 2-每周 3-每月

    @prop({ required: true })
    count: number; 		        	// 数量

    @prop({ required: true })
    seasonNum: number; 		        	// 赛季id

    private static getRefreshCondition(seasonNum: number) {
        let today = getZeroPointD();
        let cutWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
        let curMonth = getZeroPointD(SHOP_REFRESH_TYPE.MONTHLY);

        return [
            { createdAt: { $gte: today }, refreshType: SHOP_REFRESH_TYPE.DAILY },
            { createdAt: { $gte: cutWeek }, refreshType: SHOP_REFRESH_TYPE.WEEKLY },
            { createdAt: { $gte: curMonth }, refreshType: SHOP_REFRESH_TYPE.MONTHLY },
            { refreshType: SHOP_REFRESH_TYPE.FOREVER },
            { refreshType: SHOP_REFRESH_TYPE.PVP, seasonNum },
        ]

    }

    public static async findByShopType(roleId: string, shop: number, type: number, seasonNum: number) {
        let timeCondition = this.getRefreshCondition(seasonNum);
        let rec: UserShopType[] = await UserShopModel.find({ shop, type, roleId, $or: timeCondition }).lean();
        return rec;
    }

    public static async findByRoleId(roleId: string, seasonNum: number) {
        let timeCondition = this.getRefreshCondition(seasonNum);
        let rec: UserShopType[] = await UserShopModel.find({ roleId, $or: timeCondition }).lean();
        return rec;
    }

    public static async findByRoleAndItem(roleId: string, dicShopItem: { id: number, shop: number, type: number, createTime?: number }, seasonNum: number) {
        let timeCondition = this.getRefreshCondition(seasonNum);
        let { id, shop, type, createTime = 0 } = dicShopItem;

        let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId: id, shop, type, createTime, $or: timeCondition }).lean();
        return rec;
    }

    public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }, inc: number, seasonNum: number) {
        let code = genCode(8);
        let timeCondition = this.getRefreshCondition(seasonNum);
        let { id, goodId, refreshType, shop, type, createTime = 0 } = dicShopItem;

        let rec: UserShopType = await UserShopModel.findOneAndUpdate(
            { roleId, itemId: id, $or: timeCondition, shop, type, createTime }, 
            { $setOnInsert: { roleName, code, goodId, refreshType, seasonNum }, $inc: { count: inc }, $set: { activityId } },
            { new: true, upsert: true }
        ).lean();
        return rec;
    }

    /**
     * 修改已购买次数
     *
     * @static
     * @param {string} roleId
     * @param {{ id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }} dicShopItem
     * @param {number} inc: 变化次数
     * @param {number} seasonNum
     * @return {*} 
     * @memberof UserShop
     */
    public static async updateCount(roleId: string, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }, inc: number, seasonNum: number) {
        let { id, shop, type, createTime = 0 } = dicShopItem;
        let timeCondition = this.getRefreshCondition(seasonNum);
        return await UserShopModel.findOneAndUpdate(
            { roleId, itemId: id, $or: timeCondition, shop, type, createTime }, 
            { $inc: { count: inc } },
            { new: true }
        ).lean();
    }

    public static async deleteAccount(roleId: string) {
        let result = await UserShopModel.deleteMany({roleId});
        return result;
    }
}

export const UserShopModel = getModelForClass(UserShop);

export interface UserShopType extends Pick<DocumentType<UserShop>, keyof UserShop> { }
export type UserShopParam = Partial<UserShopType>;
