package dao

import (
	"fmt"
	"service/api/consts"
	bannerproto "service/api/proto/banner/proto"
	catalogproto "service/api/proto/catalog/proto"
	"service/bizcommon/util"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/qiniu/qmgo"
	"go.mongodb.org/mongo-driver/bson"

	accountproto "service/api/proto/account/proto"
	accountrelationproto "service/api/proto/accountrelation/proto"
	callhistoryproto "service/api/proto/callhistory/proto"
	contact_customer_service_proto "service/api/proto/contact_customer_service/proto"
	feedbackproto "service/api/proto/feedback/proto"
	footprintproto "service/api/proto/footprint/proto"
	imageaudittaskproto "service/api/proto/imageaudittask/proto"
	loginproto "service/api/proto/login/proto"
	momentproto "service/api/proto/moment/proto"
	productproto "service/api/proto/product/proto"
	realname_authenticationproto "service/api/proto/realname_authentication/proto"
	streamerproto "service/api/proto/streamer/proto"
	streamerauthapprovalproto "service/api/proto/streamerauthapproval/proto"
	streamerlinkproto "service/api/proto/streamerlink/proto"
	textaudittaskproto "service/api/proto/textaudittask/proto"
	thumbsupproto "service/api/proto/thumbsup/proto"
	tokenproto "service/api/proto/token/proto"
	userwxaddcheckproto "service/api/proto/userwxaddcheck/proto"
	vericodeproto "service/api/proto/vericode/proto"
	"service/app/mix/conf"
	"service/dbstruct"
	"service/library/logger"
	"service/library/mongodb"
)

type Mongo struct {
	clientMix *qmgo.Client
}

func NewMongo(cfg *conf.ConfigSt) (mongo *Mongo, err error) {
	mongo = new(Mongo)

	mongo.clientMix, err = mongodb.NewMongoClient(cfg.MixMongo)
	if err != nil {
		logger.Error("NewMongoClient fail, cfg: %v, err: %v", util.ToJson(cfg.MixMongo), err)
		return
	}

	return
}

// mongo
const (
	DBVas             = "vas"
	COLProduct        = "product"
	COLUserVasInfo    = "user_vas_info"
	COLOpLogOrder     = "oplog_order_%d"
	COLOpLogCoinOrder = "oplog_coin_order_%d"

	DBCatalog  = "catalog"
	COLCatalog = "catalog"

	DBBanner  = "banner"
	COLBanner = "banner"

	DBResource      = "resource"
	COLCatalogIndex = "l2_catalog_index"
	COLBannerIndex  = "banner_index"

	DBMedia  = "media"
	COLImage = "image"
	COLVideo = "video"

	DBLogin  = "login"
	COLLogin = "login"

	DBToken  = "token"
	COLToken = "token"

	DBAccount  = "account"
	COLAccount = "account"

	DBVeriCode  = "vericode"
	COLVeriCode = "vericode"

	DBMoment  = "moment"
	COLMoment = "moment"

	DBFootPrint  = "footprint"
	COLFootPrint = "footprint"

	DBThumbsUp  = "thumbs_up"
	COLThumbsUp = "thumbs_up"

	DBAccountRelation     = "account_relation"
	COLAccountRelation    = "account_relation"
	COLAccountRelationHis = "account_relation_his"

	DBStreamerAuthApproval     = "streamer_auth_approval"
	COLStreamerAuthApproval    = "streamer_auth_approval"
	COLStreamerAuthApprovalHis = "streamer_auth_approval_his"

	DBStreamer  = "streamer"
	COLStreamer = "streamer"

	DBFeedback  = "feedback"
	COLFeedback = "feedback"

	DBCallHistory  = "call_history"
	COLCallHistory = "call_history"

	DBStreamerLink  = "streamer_link"
	COLStreamerLink = "streamer_link"

	DBUserWxAddCheck  = "user_wx_add_check"
	COLUserWxAddCheck = "user_wx_add_check"

	DBRealNameAuthentication     = "realname_authentication"
	COLRealNameAuthentication    = "realname_authentication"
	COLRealNameAuthenticationHis = "realname_authentication_his"

	DBContactCustomerService  = "contact_customer_service"
	COLContactCustomerService = "contact_customer_service"

	DBImageAudit      = "image_audit"
	COLImageAudit     = "image_audit"
	COLImageAuditTask = "image_audit_task"

	DBTextAudit      = "text_audit"
	COLTextAudit     = "text_audit"
	COLTextAuditTask = "text_audit_task"
)

// 商品表
func (m *Mongo) getColProduct() *qmgo.Collection {
	return m.clientMix.Database(DBVas).Collection(COLProduct)
}

// 商品表
func (m *Mongo) getColUserVasInfo() *qmgo.Collection {
	return m.clientMix.Database(DBVas).Collection(COLUserVasInfo)
}

// 订单操作记录
func (m *Mongo) getColOplogOrder(orderId string) *qmgo.Collection {
	orderIdInt64, _ := strconv.ParseInt(orderId[:13], 10, 64)
	mod := orderIdInt64 % 64
	return m.clientMix.Database(DBVas).Collection(fmt.Sprintf(COLOpLogOrder, mod))
}

// 金币订单操作记录
func (m *Mongo) getColOplogCoinOrder(orderId string) *qmgo.Collection {
	orderIdInt64, _ := strconv.ParseInt(orderId[:13], 10, 64)
	mod := orderIdInt64 % 64
	return m.clientMix.Database(DBVas).Collection(fmt.Sprintf(COLOpLogCoinOrder, mod))
}

// 分类表
func (m *Mongo) getColCatalog() *qmgo.Collection {
	return m.clientMix.Database(DBCatalog).Collection(COLCatalog)
}

// banner表
func (m *Mongo) getColBanner() *qmgo.Collection {
	return m.clientMix.Database(DBBanner).Collection(COLBanner)
}

// 二级分类下发表
func (m *Mongo) getColL2CatalogIndex() *qmgo.Collection {
	return m.clientMix.Database(DBResource).Collection(COLCatalogIndex)
}

// banner下发表
func (m *Mongo) getColBannerIndex() *qmgo.Collection {
	return m.clientMix.Database(DBResource).Collection(COLBannerIndex)
}

// 图片表
func (m *Mongo) getColImage() *qmgo.Collection {
	return m.clientMix.Database(DBMedia).Collection(COLImage)
}

// 视频表
func (m *Mongo) getColVideo() *qmgo.Collection {
	return m.clientMix.Database(DBMedia).Collection(COLVideo)
}

// 登录表
func (m *Mongo) getColLogin() *qmgo.Collection {
	return m.clientMix.Database(DBLogin).Collection(COLLogin)
}

// Token表
func (m *Mongo) getColToken() *qmgo.Collection {
	return m.clientMix.Database(DBToken).Collection(COLToken)
}

// Account表
func (m *Mongo) getColAccount() *qmgo.Collection {
	return m.clientMix.Database(DBAccount).Collection(COLAccount)
}

// VeriCode表
func (m *Mongo) getColVeriCode() *qmgo.Collection {
	return m.clientMix.Database(DBVeriCode).Collection(COLVeriCode)
}

// 动态表
func (m *Mongo) getColMoment() *qmgo.Collection {
	return m.clientMix.Database(DBMoment).Collection(COLMoment)
}

// 足迹表
func (m *Mongo) getColFootPrint() *qmgo.Collection {
	return m.clientMix.Database(DBFootPrint).Collection(COLFootPrint)
}

// 点赞表
func (m *Mongo) getColThumbsUp() *qmgo.Collection {
	return m.clientMix.Database(DBThumbsUp).Collection(COLThumbsUp)
}

// 用户关系表
func (m *Mongo) getColAccountRelation() *qmgo.Collection {
	return m.clientMix.Database(DBAccountRelation).Collection(COLAccountRelation)
}

// 用户关系历史表
func (m *Mongo) getColAccountRelationHis() *qmgo.Collection {
	return m.clientMix.Database(DBAccountRelation).Collection(COLAccountRelationHis)
}

// 女神认证审批表
func (m *Mongo) getColStreamerAuthApproval() *qmgo.Collection {
	return m.clientMix.Database(DBStreamerAuthApproval).Collection(COLStreamerAuthApproval)
}

// 女神认证审批历史表
func (m *Mongo) getColStreamerAuthApprovalHis() *qmgo.Collection {
	return m.clientMix.Database(DBStreamerAuthApproval).Collection(COLStreamerAuthApprovalHis)
}

// 主播表
func (m *Mongo) getColStreamer() *qmgo.Collection {
	return m.clientMix.Database(DBStreamer).Collection(COLStreamer)
}

// 意见反馈表
func (m *Mongo) getColFeedback() *qmgo.Collection {
	return m.clientMix.Database(DBFeedback).Collection(COLFeedback)
}

// 通话记录表
func (m *Mongo) getColCallHistory() *qmgo.Collection {
	return m.clientMix.Database(DBCallHistory).Collection(COLCallHistory)
}

// 主播链接表
func (m *Mongo) getColStreamerLink() *qmgo.Collection {
	return m.clientMix.Database(DBStreamerLink).Collection(COLStreamerLink)
}

// 用户微信添加审核表
func (m *Mongo) getColUserWxAddCheck() *qmgo.Collection {
	return m.clientMix.Database(DBUserWxAddCheck).Collection(COLUserWxAddCheck)
}

// 实名认证表
func (m *Mongo) getColRealNameAuthentication() *qmgo.Collection {
	return m.clientMix.Database(DBRealNameAuthentication).Collection(COLRealNameAuthentication)
}

// 实名认证历史表
func (m *Mongo) getColRealNameAuthenticationHis() *qmgo.Collection {
	return m.clientMix.Database(DBRealNameAuthentication).Collection(COLRealNameAuthenticationHis)
}

// 联系客服表
func (m *Mongo) getColContactCustomerService() *qmgo.Collection {
	return m.clientMix.Database(DBContactCustomerService).Collection(COLContactCustomerService)
}

// 图像审核表
func (m *Mongo) getColImageAudit() *qmgo.Collection {
	return m.clientMix.Database(DBImageAudit).Collection(COLImageAudit)
}

// 图像审核任务表
func (m *Mongo) getColImageAuditTask() *qmgo.Collection {
	return m.clientMix.Database(DBImageAudit).Collection(COLImageAuditTask)
}

// 文字审核表
func (m *Mongo) getColTextAudit() *qmgo.Collection {
	return m.clientMix.Database(DBTextAudit).Collection(COLTextAudit)
}

// 文字审核任务表
func (m *Mongo) getColTextAuditTask() *qmgo.Collection {
	return m.clientMix.Database(DBTextAudit).Collection(COLTextAuditTask)
}

// 商品相关
func (m *Mongo) CreateProduct(ctx *gin.Context, product *dbstruct.Product) error {
	col := m.getColProduct()
	_, err := col.InsertOne(ctx, product)
	return err
}

func (m *Mongo) UpdateProduct(ctx *gin.Context, product *dbstruct.Product) error {
	col := m.getColProduct()
	set := qmgo.M{
		"mid":        product.Mid,
		"name":       product.Name,
		"desc":       product.Desc,
		"real_price": product.RealPrice,
		"ori_price":  product.OriPrice,
		"ut":         time.Now().Unix(),
	}
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, product.Id, up)
	return err
}

func (m *Mongo) DeleteProduct(ctx *gin.Context, id int64) error {
	col := m.getColProduct()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetProductList(ctx *gin.Context, req *productproto.OpListReq) ([]*dbstruct.Product, error) {
	list := make([]*dbstruct.Product, 0)
	col := m.getColProduct()
	query := qmgo.M{
		"del_flag": 0,
	}
	if len(req.Mids) > 0 {
		query = qmgo.M{
			"del_flag": 0,
			"mid": qmgo.M{
				"$in": req.Mids,
			},
		}
	}
	// 昵称模糊查询
	if len(req.Username) > 0 {
		query = qmgo.M{
			"del_flag": 0,
			"name": qmgo.M{
				"$regex": req.Mids,
			},
		}
	}
	// 排序key
	sortKey := ""
	if !req.Ascend {
		sortKey += "-"
	}
	switch req.SortType {
	case productproto.OpListSortTypeCt:
		sortKey += "ct"
	case productproto.OpListSortTypeScore:
		sortKey += "score"
	case productproto.OpListSortTypePrice:
		sortKey += "real_price"
	}
	if len(sortKey) <= 0 {
		sortKey = "-ct"
	}
	err := col.Find(ctx, query).Sort(sortKey).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetProductById(ctx *gin.Context, id string) (*dbstruct.Product, error) {
	product := new(dbstruct.Product)
	col := m.getColProduct()
	query := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&product)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, nil
	}
	return product, nil
}

func (m *Mongo) GetProductByDtType(ctx *gin.Context, dt int32, typ string) ([]*dbstruct.Product, error) {
	list := make([]*dbstruct.Product, 0)
	col := m.getColProduct()
	query := qmgo.M{
		"type":     typ,
		"dev_type": dt,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return make([]*dbstruct.Product, 0), nil
	}
	return list, nil
}

// 分类相关
func (m *Mongo) CreateCatalog(ctx *gin.Context, catalog *dbstruct.Catalog) error {
	col := m.getColCatalog()
	_, err := col.InsertOne(ctx, catalog)
	return err
}

func (m *Mongo) UpdateCatalog(ctx *gin.Context, catalog *dbstruct.Catalog) error {
	col := m.getColCatalog()
	set := qmgo.M{
		"name":      catalog.Name,
		"cover_id":  catalog.CoverId,
		"desc":      catalog.Desc,
		"level":     catalog.Level,
		"parent_id": catalog.ParentId,
		"ut":        time.Now().Unix(),
	}
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, catalog.Id, up)
	return err
}

func (m *Mongo) DeleteCatalog(ctx *gin.Context, id int64) error {
	col := m.getColCatalog()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetCatalogList(ctx *gin.Context, req *catalogproto.OpListReq) ([]*dbstruct.Catalog, error) {
	list := make([]*dbstruct.Catalog, 0)
	col := m.getColCatalog()
	query := qmgo.M{
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetCatalogListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Catalog, error) {
	list := make([]*dbstruct.Catalog, 0)
	col := m.getColCatalog()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// banner相关
func (m *Mongo) CreateBanner(ctx *gin.Context, banner *dbstruct.Banner) error {
	col := m.getColBanner()
	_, err := col.InsertOne(ctx, banner)
	return err
}

func (m *Mongo) UpdateBanner(ctx *gin.Context, banner *dbstruct.Banner) error {
	col := m.getColBanner()
	set := qmgo.M{
		"img_url":     banner.ImgUrl,
		"video_url":   banner.VideoUrl,
		"jump_router": banner.JumpRouter,
		"ut":          time.Now().Unix(),
	}
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, banner.Id, up)
	return err
}

func (m *Mongo) DeleteBanner(ctx *gin.Context, id int64) error {
	col := m.getColBanner()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetBannerList(ctx *gin.Context, req *bannerproto.OpListReq) ([]*dbstruct.Banner, error) {
	list := make([]*dbstruct.Banner, 0)
	col := m.getColBanner()
	query := qmgo.M{}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetBannerListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Banner, error) {
	list := make([]*dbstruct.Banner, 0)
	col := m.getColBanner()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// resource
func (m *Mongo) SetL2CatalogIndex(ctx *gin.Context, list []*dbstruct.L2CatalogIndex) error {
	col := m.getColL2CatalogIndex()
	// 清空
	_, err := col.RemoveAll(ctx, bson.M{})
	if err != nil {
		logger.Error("RemoveAll fail, err: %v", err)
		return err
	}

	// 再写
	bulk := col.Bulk()
	timeNow := time.Now().Unix()
	for _, item := range list {
		query := qmgo.M{
			"l1_id": item.L1Id,
			"l2_id": item.L2Id,
		}
		update := qmgo.M{
			"$setOnInsert": bson.M{
				"ct": timeNow,
			},
			"$set": bson.M{
				"idx": item.Idx,
				"ut":  timeNow,
			},
		}
		bulk.UpsertOne(query, update)
	}
	_, err = bulk.Run(ctx)
	if err != nil {
		logger.Error("bulk Run fail, err: %v", err)
		return err
	}
	return err
}

func (m *Mongo) GetL2CatalogIndex(ctx *gin.Context, l1Id int64) ([]*dbstruct.L2CatalogIndex, error) {
	list := make([]*dbstruct.L2CatalogIndex, 0)
	col := m.getColL2CatalogIndex()
	query := bson.M{
		"l1_id": l1Id,
	}
	err := col.Find(ctx, query).Sort("idx").All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) SetBannerIndex(ctx *gin.Context, list []*dbstruct.BannerIndex) error {
	col := m.getColBannerIndex()
	// 清空
	_, err := col.RemoveAll(ctx, bson.M{})
	if err != nil {
		logger.Error("RemoveAll fail, err: %v", err)
		return err
	}

	// 再写
	bulk := col.Bulk()
	timeNow := time.Now().Unix()
	for _, item := range list {
		query := qmgo.M{
			"id": item.Id,
		}
		update := qmgo.M{
			"$setOnInsert": bson.M{
				"ct": timeNow,
			},
			"$set": bson.M{
				"idx": item.Idx,
				"ut":  timeNow,
			},
		}
		bulk.UpsertOne(query, update)
	}
	_, err = bulk.Run(ctx)
	if err != nil {
		logger.Error("bulk Run fail, err: %v", err)
		return err
	}
	return err
}

func (m *Mongo) GetBannerIndex(ctx *gin.Context) ([]*dbstruct.BannerIndex, error) {
	list := make([]*dbstruct.BannerIndex, 0)
	col := m.getColL2CatalogIndex()
	query := bson.M{}
	err := col.Find(ctx, query).Sort("idx").All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// 图片
func (m *Mongo) SaveImage(ctx *gin.Context, image *dbstruct.Image) error {
	col := m.getColImage()
	_, err := col.InsertOne(ctx, image)
	if err != nil {
		return err
	}
	return nil
}

func (m *Mongo) GetImageById(ctx *gin.Context, id int64) (*dbstruct.Image, error) {
	image := new(dbstruct.Image)
	col := m.getColImage()
	err := col.Find(ctx, qmgo.M{"_id": id}).One(&image)
	if err != nil {
		return nil, err
	}
	return image, nil
}

func (m *Mongo) GetImageByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Image, error) {
	list := make([]*dbstruct.Image, 0)
	col := m.getColImage()
	err := col.Find(ctx, qmgo.M{"_id": qmgo.M{"$in": ids}}).All(&list)
	if err != nil {
		return nil, err
	}
	return list, nil
}

// 视频
func (m *Mongo) SaveVideo(ctx *gin.Context, video *dbstruct.Video) error {
	col := m.getColVideo()
	_, err := col.InsertOne(ctx, video)
	if err != nil {
		return err
	}
	return nil
}

func (m *Mongo) GetVideoById(ctx *gin.Context, id int64) (*dbstruct.Video, error) {
	video := new(dbstruct.Video)
	col := m.getColVideo()
	err := col.Find(ctx, qmgo.M{"_id": id}).One(&video)
	if err != nil {
		return nil, err
	}
	return video, nil
}

func (m *Mongo) GetVideoByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.Video, error) {
	list := make([]*dbstruct.Video, 0)
	col := m.getColVideo()
	err := col.Find(ctx, qmgo.M{"_id": qmgo.M{"$in": ids}}).All(&list)
	if err != nil {
		return nil, err
	}
	return list, nil
}

// 登录表
func (m *Mongo) CreateLogin(ctx *gin.Context, login *dbstruct.Login) error {
	col := m.getColLogin()
	_, err := col.InsertOne(ctx, login)
	return err
}

func (m *Mongo) UpdateLogin(ctx *gin.Context, login *dbstruct.Login) error {
	col := m.getColLogin()
	set := util.EntityToM(login)
	set["ut"] = time.Now().Unix()

	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, util.DerefInt64(login.Id), up)
	return err
}

func (m *Mongo) DeleteLogin(ctx *gin.Context, id int64) error {
	col := m.getColLogin()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetLoginListByPhoneHash(ctx *gin.Context, req *loginproto.OpListByPhoneHashReq) (*dbstruct.Login, error) {
	login := &dbstruct.Login{}
	col := m.getColLogin()
	query := qmgo.M{
		"phone_hash":  req.PhoneHash,
		"region_code": req.RegionCode,
		"del_flag":    0,
	}
	err := col.Find(ctx, query).One(login)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return login, err
}

func (m *Mongo) UpdateLoginByMid(ctx *gin.Context, login *dbstruct.Login, mid int64) error {
	col := m.getColLogin()
	set := util.EntityToM(login)
	set["ut"] = time.Now().Unix()

	up := qmgo.M{
		"$set": set,
	}

	filter := qmgo.M{
		"mid": mid,
	}
	err := col.UpdateOne(ctx, filter, up)
	return err
}

// 令牌表
func (m *Mongo) CreateToken(ctx *gin.Context, token *dbstruct.Token) error {
	col := m.getColToken()
	_, err := col.InsertOne(ctx, token)
	return err
}

func (m *Mongo) DeleteToken(ctx *gin.Context, id int64) error {
	col := m.getColToken()

	err := col.Remove(ctx, qmgo.M{
		"_id": id,
	})
	return err
}

func (m *Mongo) DeleteTokenByMid(ctx *gin.Context, mid int64) error {
	col := m.getColToken()

	err := col.Remove(ctx, qmgo.M{
		"mid": mid,
	})
	return err
}

func (m *Mongo) GetTokenList(ctx *gin.Context, req *tokenproto.OpListReq) ([]*dbstruct.Token, error) {
	list := make([]*dbstruct.Token, 0)
	col := m.getColToken()
	query := qmgo.M{
		"_id": req.Id,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// account相关
func (m *Mongo) CreateAccount(ctx *gin.Context, account *dbstruct.Account) error {
	col := m.getColAccount()
	_, err := col.InsertOne(ctx, account)
	return err
}

func (m *Mongo) UpdateAccount(ctx *gin.Context, account *dbstruct.Account) error {
	col := m.getColAccount()
	set := util.EntityToM(account)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, util.DerefInt64(account.Mid), up)
	return err
}

func (m *Mongo) DeleteAccount(ctx *gin.Context, id int64) error {
	col := m.getColAccount()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetAccountListByMid(ctx *gin.Context, req *accountproto.OpListByMidReq) (*dbstruct.Account, error) {
	col := m.getColAccount()
	account := &dbstruct.Account{}

	query := qmgo.M{
		"_id":      util.DerefInt64(req.Mid),
		"del_flag": 0,
	}

	err := col.Find(ctx, query).One(account)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	if err != nil {
		return nil, err
	}
	return account, err
}

func (m *Mongo) GetAccountListByMids(ctx *gin.Context, req *accountproto.OpListByMidsReq) ([]*dbstruct.Account, error) {
	list := make([]*dbstruct.Account, 0)
	col := m.getColAccount()
	query := qmgo.M{
		"del_flag": 0,
		"_id": bson.M{
			"$in": req.Mids,
		},
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "-ct")
	}

	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetAccountListByUserId(ctx *gin.Context, req *accountproto.OpListByUserIdReq) (*dbstruct.Account, error) {
	col := m.getColAccount()
	account := &dbstruct.Account{}

	query := qmgo.M{
		"user_id":  util.DerefInt64(req.UserId),
		"del_flag": 0,
	}

	err := col.Find(ctx, query).One(account)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	if err != nil {
		return nil, err
	}
	return account, err
}

func (m *Mongo) GetAccountListFuzzilyByName(ctx *gin.Context, req *accountproto.OpListFuzzilyByNameReq) ([]*dbstruct.Account, error) {
	list := make([]*dbstruct.Account, 0)
	col := m.getColAccount()
	query := qmgo.M{
		"del_flag": 0,
		"name": bson.M{
			"$regex": req.Name,
		},
	}
	if req.Role != nil {
		query["role"] = util.DerefInt64(req.Role)
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "-ct")
	}

	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetAccountListFuzzilyByUserId(ctx *gin.Context, req *accountproto.OpListFuzzilyByUserIdReq) ([]*dbstruct.Account, error) {
	list := make([]*dbstruct.Account, 0)
	col := m.getColAccount()
	query := qmgo.M{
		"del_flag": 0,
		"$or": []bson.M{
			{
				"name": bson.M{
					"$regex": fmt.Sprint(util.DerefInt64(req.UserId)),
				},
			},
			{
				"$expr": bson.M{
					"$regexMatch": bson.M{
						"input": bson.M{
							"$toString": "$user_id",
						},
						"regex": fmt.Sprint(util.DerefInt64(req.UserId)),
					},
				},
			},
		},
	}
	if req.Role != nil {
		query["role"] = util.DerefInt64(req.Role)
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "-ct")
	}

	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateAccountByIds(ctx *gin.Context, account *dbstruct.Account, ids []int64) error {
	col := m.getColAccount()
	set := util.EntityToM(account)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

// vericode相关
func (m *Mongo) CreateVeriCode(ctx *gin.Context, vericode *dbstruct.VeriCode) error {
	col := m.getColVeriCode()
	_, err := col.InsertOne(ctx, vericode)
	return err
}

func (m *Mongo) DeleteVeriCode(ctx *gin.Context, id int64) error {
	col := m.getColVeriCode()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	filter := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}
	err := col.UpdateOne(ctx, filter, update)
	return err
}

func (m *Mongo) GetVeriCodeListByPhoneHash(ctx *gin.Context, req *vericodeproto.OpListByPhoneHashReq) (*dbstruct.VeriCode, error) {
	vericode := &dbstruct.VeriCode{}
	col := m.getColVeriCode()
	query := qmgo.M{
		"phone_hash":  req.PhoneHash,
		"region_code": req.RegionCode,
		"del_flag":    consts.Exist,
	}
	err := col.Find(ctx, query).Sort("-ct").One(vericode)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return vericode, err
	}
	return vericode, err
}

// 动态相关
func (m *Mongo) CreateMoment(ctx *gin.Context, moment *dbstruct.Moment) error {
	col := m.getColMoment()
	_, err := col.InsertOne(ctx, moment)
	return err
}

func (m *Mongo) UpdateMoment(ctx *gin.Context, moment *dbstruct.Moment) error {
	col := m.getColMoment()
	set := util.EntityToM(moment)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, moment.Id, up)
	return err
}

func (m *Mongo) DeleteMoment(ctx *gin.Context, id int64) error {
	col := m.getColMoment()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetMomentList(ctx *gin.Context, req *momentproto.OpListReq) ([]*dbstruct.Moment, error) {
	list := make([]*dbstruct.Moment, 0)
	col := m.getColMoment()
	//ct_lower_bound < ct <= ct_upper_bound
	query := qmgo.M{
		"mid": bson.M{
			"$in": req.Mids,
		},
		"ct": bson.M{
			"$gt":  req.CtLowerBound,
			"$lte": req.CtUpperBound,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) ThumbsUpMoment(ctx *gin.Context, req *momentproto.OpThumbsUpReq) (moment *dbstruct.Moment, err error) {
	col := m.getColMoment()
	change := qmgo.Change{
		Update:    qmgo.M{"$inc": qmgo.M{"thumbs_up_num": req.Times}},
		Upsert:    true,
		ReturnNew: false,
	}
	momentInstance := dbstruct.Moment{}
	if err = col.Find(ctx, qmgo.M{"_id": req.MomentId}).Apply(change, &momentInstance); err != nil {
		logger.Error("change error : %v", err)
		return
	}
	return &momentInstance, err
}

// 足迹相关
func (m *Mongo) CreateFootPrint(ctx *gin.Context, footprint []*dbstruct.FootPrint) error {
	col := m.getColFootPrint()
	_, err := col.InsertMany(ctx, footprint)
	return err
}

func (m *Mongo) DeleteFootPrint(ctx *gin.Context, req *footprintproto.OpDeleteReq) error {
	col := m.getColFootPrint()

	orClause := make([]qmgo.M, 0)
	for _, footprint := range req.FootPrints {
		orClause = append(orClause, qmgo.M{
			"sub_mid":   util.DerefInt64(footprint.SubMid),
			"obj_mid":   util.DerefInt64(footprint.ObjMid),
			"predicate": util.DerefInt64(footprint.Predicate),
		})
	}

	filter := qmgo.M{
		"$or": orClause,
	}

	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	_, err := col.UpdateAll(ctx, filter, update)
	return err
}

func (m *Mongo) GetViewFootPrintList(ctx *gin.Context, req *footprintproto.OpListReq) ([]*dbstruct.FootPrint, error) {
	list := make([]*dbstruct.FootPrint, 0)
	col := m.getColFootPrint()
	query := qmgo.M{
		"sub_mid":   req.Mid,
		"predicate": consts.View,
		"del_flag":  0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetIsViewedFootPrintList(ctx *gin.Context, req *footprintproto.OpListReq) ([]*dbstruct.FootPrint, error) {
	list := make([]*dbstruct.FootPrint, 0)
	col := m.getColFootPrint()
	query := qmgo.M{
		"sub_mid":   req.Mid,
		"predicate": consts.IsViewed,
		"del_flag":  0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetFootPrintCount(ctx *gin.Context, req *footprintproto.OpCountReq) (results []map[string]interface{}, err error) {
	col := m.getColFootPrint()
	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"sub_mid":  req.Mid,
			"del_flag": 0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$predicate"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	pipeline := qmgo.Pipeline{matchClause, groupClause}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

// 点赞相关
func (m *Mongo) CreateThumbsUp(ctx *gin.Context, thumbsup *dbstruct.ThumbsUp) error {
	col := m.getColThumbsUp()
	_, err := col.InsertOne(ctx, thumbsup)
	return err
}

func (m *Mongo) DeleteThumbsUp(ctx *gin.Context, req *thumbsupproto.OpDeleteReq) error {
	col := m.getColThumbsUp()
	filter := qmgo.M{
		"moment_id": req.MomentId,
		"mid":       req.Mid,
	}
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateOne(ctx, filter, update)
	return err
}

func (m *Mongo) GetThumbsUpList(ctx *gin.Context, req *thumbsupproto.OpListReq) ([]*dbstruct.ThumbsUp, error) {
	list := make([]*dbstruct.ThumbsUp, 0)
	col := m.getColThumbsUp()
	query := qmgo.M{
		"moment_id": req.MomentId,
		"del_flag":  0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// 用户关系相关
func (m *Mongo) CreateAccountRelation(ctx *gin.Context, accountrelations []*dbstruct.AccountRelation) error {
	col := m.getColAccountRelation()
	_, err := col.InsertMany(ctx, accountrelations)
	return err
}

func (m *Mongo) UpdateAccountRelationBySentence(ctx *gin.Context, accountrelation *dbstruct.AccountRelation, sentence *dbstruct.AccountRelation) error {
	col := m.getColAccountRelation()

	filter := qmgo.M{
		"sub_mid":   sentence.SubMid,
		"obj_mid":   sentence.ObjMid,
		"predicate": sentence.Predicate,
	}

	set := util.EntityToM(accountrelation)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateOne(ctx, filter, up)
	return err
}

func (m *Mongo) DeleteAccountRelationByIds(ctx *gin.Context, ids []int64) error {
	col := m.getColAccountRelation()

	filter := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}

	_, err := col.RemoveAll(ctx, filter)
	return err
}

func (m *Mongo) GetAccountRelationListBySubMidAndPredicate(ctx *gin.Context, req *accountrelationproto.OpListBySubMidAndPredicateReq) ([]*dbstruct.AccountRelation, error) {
	list := make([]*dbstruct.AccountRelation, 0)
	col := m.getColAccountRelation()
	query := qmgo.M{
		"sub_mid":   util.DerefInt64(req.SubMid),
		"predicate": util.DerefInt64(req.Predicate),
		"del_flag":  0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetFriendAccountRelationList(ctx *gin.Context, req *accountrelationproto.OpListReq) (results []map[string]interface{}, err error) {
	col := m.getColAccountRelation()

	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"sub_mid": util.DerefInt64(req.Mid),
			"predicate": bson.M{
				"$in": [2]int{consts.Follow, consts.IsFollowed},
			},
			"del_flag": 0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$obj_mid"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	havingClause := bson.D{{
		Key: "$match", Value: bson.M{
			"count": 2,
		},
	}}

	sortClause := bson.D{{
		Key: "$sort", Value: bson.M{
			"ct": -1,
		},
	}}

	pipeline := qmgo.Pipeline{matchClause, groupClause, havingClause, sortClause}

	if req.Offset > 0 {
		pipeline = append(pipeline, bson.D{
			{Key: "$skip", Value: req.Offset},
		})
	}

	if req.Limit > 0 {
		pipeline = append(pipeline, bson.D{
			{Key: "$limit", Value: req.Offset},
		})
	}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

func (m *Mongo) GetFriendAccountRelationCount(ctx *gin.Context, req *accountrelationproto.OpCountReq) (results []map[string]interface{}, err error) {
	col := m.getColAccountRelation()

	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"sub_mid": util.DerefInt64(req.Mid),
			"predicate": bson.M{
				"$in": [2]int{consts.Follow, consts.IsFollowed},
			},
			"del_flag": 0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$obj_mid"},
			{Key: "relation_count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	havingClause := bson.D{{
		Key: "$match", Value: bson.M{
			"relation_count": 2,
		},
	}}

	secondOrderGroupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$relation_count"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		}},
	}

	pipeline := qmgo.Pipeline{matchClause, groupClause, havingClause, secondOrderGroupClause}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

func (m *Mongo) GetAccountRelationCount(ctx *gin.Context, req *accountrelationproto.OpCountReq) (results []map[string]interface{}, err error) {
	col := m.getColAccountRelation()
	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"sub_mid": util.DerefInt64(req.Mid),
			"predicate": bson.M{
				"$in": [2]int{consts.Follow, consts.IsFollowed},
			},
			"del_flag": 0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$predicate"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	pipeline := qmgo.Pipeline{matchClause, groupClause}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

// 粉丝计数并排序,由于只有主播才会有粉丝,因此不需要加条件
func (m *Mongo) GetIsFollowedAccountRelationCount(ctx *gin.Context) (results []map[string]interface{}, err error) {
	col := m.getColAccountRelation()

	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"predicate": consts.IsFollowed,
			"del_flag":  0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$sub_mid"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	sortClause := bson.D{
		{Key: "$sort", Value: bson.M{
			"count": -1,
		},
		},
	}

	pipeline := qmgo.Pipeline{matchClause, groupClause, sortClause}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

// 按主谓宾条件查找
func (m *Mongo) GetAccountRelationBySentence(ctx *gin.Context, req *accountrelationproto.OpListBySentenceReq) (accountrelation *dbstruct.AccountRelation, err error) {
	col := m.getColAccountRelation()

	query := qmgo.M{
		"sub_mid":   util.DerefInt64(req.SubMid),
		"obj_mid":   util.DerefInt64(req.ObjMid),
		"predicate": util.DerefInt64(req.Predicate),
		"del_flag":  0,
	}

	accountrelation = new(dbstruct.AccountRelation)
	err = col.Find(ctx, query).One(accountrelation)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return
}

func (m *Mongo) GetAccountRelationBySentences(ctx *gin.Context, sentences []*dbstruct.AccountRelation) (list []*dbstruct.AccountRelation, err error) {
	col := m.getColAccountRelation()

	list = make([]*dbstruct.AccountRelation, 0)
	orClause := make([]qmgo.M, len(sentences))
	for i, sentence := range sentences {
		orClause[i] = qmgo.M{
			"sub_mid":   sentence.SubMid,
			"obj_mid":   sentence.ObjMid,
			"predicate": sentence.Predicate,
			"del_flag":  0,
		}
	}

	filter := qmgo.M{
		"$or": orClause,
	}
	err = col.Find(ctx, filter).Sort("-ct").All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) CreateAccountRelationHis(ctx *gin.Context, accountrelations []*dbstruct.AccountRelation) error {
	col := m.getColAccountRelationHis()
	_, err := col.InsertMany(ctx, accountrelations)
	return err
}

// 女神认证审批表相关
func (m *Mongo) CreateStreamerAuthApproval(ctx *gin.Context, streamerauthapproval *dbstruct.StreamerAuthApproval) error {
	col := m.getColStreamerAuthApproval()
	_, err := col.InsertOne(ctx, streamerauthapproval)
	return err
}

func (m *Mongo) UpdateStreamerAuthApproval(ctx *gin.Context, streamerauthapproval *dbstruct.StreamerAuthApproval) error {
	col := m.getColStreamerAuthApproval()
	set := util.EntityToM(streamerauthapproval)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, streamerauthapproval.Id, up)
	return err
}

func (m *Mongo) DeleteStreamerAuthApproval(ctx *gin.Context, id int64) error {
	col := m.getColStreamerAuthApproval()
	filter := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}

	_, err := col.RemoveAll(ctx, filter)
	return err
}

func (m *Mongo) DeleteStreamerAuthApprovalByIds(ctx *gin.Context, ids []int64) error {
	col := m.getColStreamerAuthApproval()
	filter := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}

	_, err := col.RemoveAll(ctx, filter)
	return err
}

func (m *Mongo) GetStreamerAuthApprovalList(ctx *gin.Context, req *streamerauthapprovalproto.OpListReq) ([]*dbstruct.StreamerAuthApproval, error) {
	list := make([]*dbstruct.StreamerAuthApproval, 0)
	col := m.getColStreamerAuthApproval()
	query := qmgo.M{
		"del_flag": 0,
	}
	if req.Status != nil {
		query["status"] = util.DerefInt64(req.Status)
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetStreamerAuthApprovalListByMid(ctx *gin.Context, req *streamerauthapprovalproto.OpListByMidReq) (*dbstruct.StreamerAuthApproval, error) {
	streamerauthapproval := &dbstruct.StreamerAuthApproval{}
	col := m.getColStreamerAuthApproval()
	query := qmgo.M{
		"mid":      util.DerefInt64(req.Mid),
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&streamerauthapproval)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return streamerauthapproval, err
}

func (m *Mongo) GetStreamerAuthApprovalListById(ctx *gin.Context, id int64) (*dbstruct.StreamerAuthApproval, error) {
	streamerauthapproval := &dbstruct.StreamerAuthApproval{}
	col := m.getColStreamerAuthApproval()
	query := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&streamerauthapproval)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return streamerauthapproval, err
}

func (m *Mongo) GetStreamerAuthApprovalListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.StreamerAuthApproval, error) {
	list := make([]*dbstruct.StreamerAuthApproval, 0)
	col := m.getColStreamerAuthApproval()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateStreamerAuthApprovalByIds(ctx *gin.Context, streamerauthapproval *dbstruct.StreamerAuthApproval, ids []int64) error {
	col := m.getColStreamerAuthApproval()
	set := util.EntityToM(streamerauthapproval)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) CreateStreamerAuthApprovalHis(ctx *gin.Context, streamerauthapproval *dbstruct.StreamerAuthApproval) error {
	col := m.getColStreamerAuthApprovalHis()
	_, err := col.InsertOne(ctx, streamerauthapproval)
	return err
}

func (m *Mongo) CreateBatchStreamerAuthApprovalHis(ctx *gin.Context, streamerauthapprovals []*dbstruct.StreamerAuthApproval) error {
	col := m.getColStreamerAuthApprovalHis()
	_, err := col.InsertMany(ctx, streamerauthapprovals)
	return err
}

// 主播相关
func (m *Mongo) CreateStreamer(ctx *gin.Context, streamer *dbstruct.Streamer) error {
	col := m.getColStreamer()
	_, err := col.InsertOne(ctx, streamer)
	return err
}

func (m *Mongo) UpdateStreamer(ctx *gin.Context, streamer *dbstruct.Streamer) error {
	col := m.getColStreamer()
	set := util.EntityToM(streamer)
	set["ut"] = time.Now().Unix()
	filter := qmgo.M{
		"mid": util.DerefInt64(streamer.Mid),
	}
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateOne(ctx, filter, up)
	return err
}

func (m *Mongo) DeleteStreamer(ctx *gin.Context, id int64) error {
	col := m.getColStreamer()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetStreamerListByMid(ctx *gin.Context, req *streamerproto.OpListByMidReq) (*dbstruct.Streamer, error) {
	col := m.getColStreamer()

	streamer := &dbstruct.Streamer{}

	query := qmgo.M{
		"del_flag": 0,
		"mid":      util.DerefInt64(req.Mid),
	}
	err := col.Find(ctx, query).One(streamer)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return streamer, err
}

func (m *Mongo) GetStreamerListByMids(ctx *gin.Context, req *streamerproto.OpListByMidsReq) ([]*dbstruct.Streamer, error) {
	col := m.getColStreamer()
	list := make([]*dbstruct.Streamer, 0)
	query := qmgo.M{
		"del_flag": 0,
		"mid": qmgo.M{
			"$in": req.Mids,
		},
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "-ct")
	}
	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	return list, err
}

func (m *Mongo) GetStreamerList(ctx *gin.Context, req *streamerproto.OpListReq) ([]*dbstruct.Streamer, error) {
	list := make([]*dbstruct.Streamer, 0)
	col := m.getColStreamer()
	query := qmgo.M{
		"del_flag": 0,
	}
	//排序规则
	if req.Sort == "" {
		req.Sort = "-ct"
	}
	err := col.Find(ctx, query).Sort(req.Sort).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) CreateBatchStreamer(ctx *gin.Context, streamers []*dbstruct.Streamer) error {
	col := m.getColStreamer()
	_, err := col.InsertMany(ctx, streamers)
	return err
}

// 意见反馈相关
func (m *Mongo) CreateFeedback(ctx *gin.Context, feedback *dbstruct.Feedback) error {
	col := m.getColFeedback()
	_, err := col.InsertOne(ctx, feedback)
	return err
}

func (m *Mongo) UpdateFeedback(ctx *gin.Context, feedback *dbstruct.Feedback) error {
	col := m.getColFeedback()
	set := util.EntityToM(feedback)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, feedback.Id, up)
	return err
}

func (m *Mongo) DeleteFeedback(ctx *gin.Context, id int64) error {
	col := m.getColFeedback()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetFeedbackList(ctx *gin.Context, req *feedbackproto.OpListReq) ([]*dbstruct.Feedback, error) {
	list := make([]*dbstruct.Feedback, 0)
	col := m.getColFeedback()
	query := qmgo.M{
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// 通话记录相关
func (m *Mongo) CreateCallHistory(ctx *gin.Context, callhistory *dbstruct.CallHistory) error {
	col := m.getColCallHistory()
	_, err := col.InsertOne(ctx, callhistory)
	return err
}

func (m *Mongo) UpdateCallHistory(ctx *gin.Context, callhistory *dbstruct.CallHistory) error {
	col := m.getColCallHistory()
	set := util.EntityToM(callhistory)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, callhistory.Id, up)
	return err
}

func (m *Mongo) DeleteCallHistory(ctx *gin.Context, id int64) error {
	col := m.getColCallHistory()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetCallHistoryList(ctx *gin.Context, req *callhistoryproto.OpListReq) ([]*dbstruct.CallHistory, error) {
	list := make([]*dbstruct.CallHistory, 0)
	col := m.getColCallHistory()
	query := qmgo.M{
		"obj_mid":  req.Mid,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetCallHistorynCount(ctx *gin.Context, req *callhistoryproto.OpCountReq) (results []map[string]interface{}, err error) {
	col := m.getColCallHistory()
	matchClause := bson.D{{
		Key: "$match", Value: bson.M{
			"obj_mid":  req.Mid,
			"del_flag": 0,
		},
	}}

	groupClause := bson.D{
		{Key: "$group", Value: bson.D{
			{Key: "_id", Value: "$predicate"},
			{Key: "count", Value: bson.M{
				"$sum": 1,
			}},
		},
		},
	}

	pipeline := qmgo.Pipeline{matchClause, groupClause}

	err = col.Aggregate(ctx, pipeline).All(&results)
	if err != nil {
		logger.Error("err : %v", err)
		return
	}

	return
}

// 主播链接相关
func (m *Mongo) CreateStreamerLink(ctx *gin.Context, streamerlink *dbstruct.StreamerLink) error {
	col := m.getColStreamerLink()
	_, err := col.InsertOne(ctx, streamerlink)
	return err
}

func (m *Mongo) UpdateStreamerLink(ctx *gin.Context, streamerlink *dbstruct.StreamerLink) error {
	col := m.getColStreamerLink()
	set := util.EntityToM(streamerlink)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, streamerlink.Id, up)
	return err
}

func (m *Mongo) DeleteStreamerLink(ctx *gin.Context, id int64) error {
	col := m.getColStreamerLink()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetStreamerLinkListByMid(ctx *gin.Context, req *streamerlinkproto.OpListByMidReq) ([]*dbstruct.StreamerLink, error) {
	list := make([]*dbstruct.StreamerLink, 0)
	col := m.getColStreamerLink()
	query := qmgo.M{
		"del_flag": 0,
		"mid":      util.DerefInt64(req.Mid),
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "order")
	}
	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetStreamerLinkListByMids(ctx *gin.Context, req *streamerlinkproto.OpListByMidsReq) ([]*dbstruct.StreamerLink, error) {
	list := make([]*dbstruct.StreamerLink, 0)
	col := m.getColStreamerLink()
	query := qmgo.M{
		"del_flag": 0,
		"mid": qmgo.M{
			"$in": req.Mids,
		},
	}
	if len(req.Sort) == 0 {
		req.Sort = append(req.Sort, "order")
	}
	err := col.Find(ctx, query).Sort(req.Sort...).Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) CreateBatchStreamerLink(ctx *gin.Context, streamerlinks []*dbstruct.StreamerLink) error {
	col := m.getColStreamerLink()
	_, err := col.InsertMany(ctx, streamerlinks)
	return err
}

func (m *Mongo) DeleteStreamerLinkByIds(ctx *gin.Context, ids []int64) error {
	col := m.getColStreamerLink()
	filter := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}

	_, err := col.UpdateAll(ctx, filter, update)
	return err
}

// 用户微信添加审核相关
func (m *Mongo) CreateUserWxAddCheck(ctx *gin.Context, userwxaddcheck *dbstruct.UserWxAddCheck) error {
	col := m.getColUserWxAddCheck()
	_, err := col.InsertOne(ctx, userwxaddcheck)
	return err
}

func (m *Mongo) UpdateUserWxAddCheck(ctx *gin.Context, userwxaddcheck *dbstruct.UserWxAddCheck) error {
	col := m.getColUserWxAddCheck()
	set := util.EntityToM(userwxaddcheck)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, userwxaddcheck.Id, up)
	return err
}

func (m *Mongo) DeleteUserWxAddCheck(ctx *gin.Context, id int64) error {
	col := m.getColUserWxAddCheck()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetUserWxAddCheckList(ctx *gin.Context, req *userwxaddcheckproto.OpListReq) ([]*dbstruct.UserWxAddCheck, error) {
	list := make([]*dbstruct.UserWxAddCheck, 0)
	col := m.getColUserWxAddCheck()
	query := qmgo.M{
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// 实名认证相关
func (m *Mongo) CreateRealNameAuthentication(ctx *gin.Context, realname_authentication *dbstruct.RealNameAuthentication) error {
	col := m.getColRealNameAuthentication()
	_, err := col.InsertOne(ctx, realname_authentication)
	return err
}

func (m *Mongo) UpdateRealNameAuthentication(ctx *gin.Context, realname_authentication *dbstruct.RealNameAuthentication) error {
	col := m.getColRealNameAuthentication()
	set := util.EntityToM(realname_authentication)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, realname_authentication.Id, up)
	return err
}

func (m *Mongo) DeleteRealNameAuthenticationByIds(ctx *gin.Context, ids []int64) error {
	col := m.getColRealNameAuthentication()
	filter := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}

	_, err := col.RemoveAll(ctx, filter)
	return err
}

func (m *Mongo) GetRealNameAuthenticationList(ctx *gin.Context, req *realname_authenticationproto.OpListReq) ([]*dbstruct.RealNameAuthentication, error) {
	list := make([]*dbstruct.RealNameAuthentication, 0)
	col := m.getColRealNameAuthentication()
	query := qmgo.M{
		"del_flag": 0,
	}
	if req.Status != nil {
		query["status"] = util.DerefInt64(req.Status)
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateRealNameAuthenticationByIds(ctx *gin.Context, realname_authentication *dbstruct.RealNameAuthentication, ids []int64) error {
	col := m.getColRealNameAuthentication()
	set := util.EntityToM(realname_authentication)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) GetRealNameAuthenticationListByIds(ctx *gin.Context, ids []int64) ([]*dbstruct.RealNameAuthentication, error) {
	list := make([]*dbstruct.RealNameAuthentication, 0)
	col := m.getColRealNameAuthentication()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) CreateBatchRealNameAuthenticationHis(ctx *gin.Context, realname_authentications []*dbstruct.RealNameAuthentication) error {
	col := m.getColRealNameAuthenticationHis()
	_, err := col.InsertMany(ctx, realname_authentications)
	return err
}

func (m *Mongo) GetRealNameAuthenticationListByMid(ctx *gin.Context, req *realname_authenticationproto.OpListByMidReq) (*dbstruct.RealNameAuthentication, error) {
	realname_authentication := &dbstruct.RealNameAuthentication{}
	col := m.getColRealNameAuthentication()
	query := qmgo.M{
		"mid":      util.DerefInt64(req.Mid),
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&realname_authentication)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return realname_authentication, err
}

// 联系客服相关
func (m *Mongo) CreateContactCustomerService(ctx *gin.Context, contact_customer_service *dbstruct.ContactCustomerService) error {
	col := m.getColContactCustomerService()
	_, err := col.InsertOne(ctx, contact_customer_service)
	return err
}

func (m *Mongo) UpdateContactCustomerServiceByIds(ctx *gin.Context, contact_customer_service *dbstruct.ContactCustomerService, ids []int64) error {
	col := m.getColContactCustomerService()
	set := util.EntityToM(contact_customer_service)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) DeleteContactCustomerService(ctx *gin.Context, id int64) error {
	col := m.getColContactCustomerService()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetContactCustomerServiceListUnread(ctx *gin.Context, req *contact_customer_service_proto.OpListReq) ([]*dbstruct.ContactCustomerService, error) {
	list := make([]*dbstruct.ContactCustomerService, 0)
	col := m.getColContactCustomerService()
	query := qmgo.M{
		"is_read":  consts.ContactCustomerService_NotRead,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) GetContactCustomerServiceListByMid(ctx *gin.Context, req *contact_customer_service_proto.OpListByMidReq) ([]*dbstruct.ContactCustomerService, error) {
	list := make([]*dbstruct.ContactCustomerService, 0)
	col := m.getColContactCustomerService()
	query := qmgo.M{
		"sub_mid":  util.DerefInt64(req.Mid),
		"del_flag": 0,
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

// 图像审核相关
func (m *Mongo) CreateImageAudit(ctx *gin.Context, imageaudit *dbstruct.ImageAudit) error {
	col := m.getColImageAudit()
	_, err := col.InsertOne(ctx, imageaudit)
	return err
}

func (m *Mongo) UpdateImageAudit(ctx *gin.Context, imageaudit *dbstruct.ImageAudit) error {
	col := m.getColImageAudit()
	set := util.EntityToM(imageaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, imageaudit.Id, up)
	return err
}

func (m *Mongo) DeleteImageAudit(ctx *gin.Context, id string) error {
	col := m.getColImageAudit()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetImageAuditList(ctx *gin.Context, id string) (*dbstruct.ImageAudit, error) {
	imageaudit := &dbstruct.ImageAudit{}
	col := m.getColImageAudit()
	query := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&imageaudit)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return imageaudit, err
}

func (m *Mongo) GetImageAuditListByIds(ctx *gin.Context, ids []string) ([]*dbstruct.ImageAudit, error) {
	list := make([]*dbstruct.ImageAudit, 0)
	col := m.getColImageAudit()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) CreateImageAuditBatch(ctx *gin.Context, imageaudits []*dbstruct.ImageAudit) error {
	col := m.getColImageAudit()
	_, err := col.InsertMany(ctx, imageaudits)
	return err
}

func (m *Mongo) UpdateImageAuditByIds(ctx *gin.Context, imageaudit *dbstruct.ImageAudit, ids []string) error {
	col := m.getColImageAudit()
	set := util.EntityToM(imageaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) UpdateImageAuditByBatchId(ctx *gin.Context, batchId string, imageaudit *dbstruct.ImageAudit) error {
	col := m.getColImageAudit()
	set := util.EntityToM(imageaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"batch_id": batchId,
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

// 图像审核任务相关
func (m *Mongo) CreateImageAuditTask(ctx *gin.Context, imageaudittask *dbstruct.ImageAuditTask) error {
	col := m.getColImageAuditTask()
	_, err := col.InsertOne(ctx, imageaudittask)
	return err
}

func (m *Mongo) UpdateImageAuditTask(ctx *gin.Context, imageaudittask *dbstruct.ImageAuditTask) error {
	col := m.getColImageAuditTask()
	set := util.EntityToM(imageaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, imageaudittask.Id, up)
	return err
}

func (m *Mongo) DeleteImageAuditTask(ctx *gin.Context, id string) error {
	col := m.getColImageAuditTask()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetImageAuditTaskList(ctx *gin.Context, req *imageaudittaskproto.OpListReq) ([]*dbstruct.ImageAuditTask, error) {
	list := make([]*dbstruct.ImageAuditTask, 0)
	col := m.getColImageAuditTask()
	query := qmgo.M{
		"del_flag": 0,
	}
	if req.RouteUrl != nil {
		query["route_url"] = util.DerefString(req.RouteUrl)
	}
	if req.AssociativeDatabase != nil {
		query["associative_data_base"] = util.DerefString(req.AssociativeDatabase)
	}
	if req.AssociativeTableName != nil {
		query["associative_tabel_name"] = util.DerefString(req.AssociativeTableName)
	}
	if req.AssociativeTableId != nil {
		query["associative_tabel_id"] = util.DerefInt64(req.AssociativeTableId)
	}
	if req.AssociativeTableColumn != nil {
		query["associative_tabel_column"] = util.DerefString(req.AssociativeTableColumn)
	}
	if req.BatchId != nil {
		query["batch_id"] = util.DerefString(req.BatchId)
	}
	if req.Status != nil {
		query["status"] = util.DerefInt64(req.Status)
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateImageAuditTaskByBatchId(ctx *gin.Context, batchId string, imageaudittask *dbstruct.ImageAuditTask) error {
	col := m.getColImageAuditTask()
	set := util.EntityToM(imageaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"batch_id": batchId,
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) UpdateImageAuditTaskByIds(ctx *gin.Context, imageaudittask *dbstruct.ImageAuditTask, ids []string) error {
	col := m.getColImageAuditTask()
	set := util.EntityToM(imageaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

// 文字审核相关
func (m *Mongo) CreateTextAudit(ctx *gin.Context, textaudit *dbstruct.TextAudit) error {
	col := m.getColTextAudit()
	_, err := col.InsertOne(ctx, textaudit)
	return err
}

func (m *Mongo) UpdateTextAudit(ctx *gin.Context, textaudit *dbstruct.TextAudit) error {
	col := m.getColTextAudit()
	set := util.EntityToM(textaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, textaudit.Id, up)
	return err
}

func (m *Mongo) DeleteTextAudit(ctx *gin.Context, id string) error {
	col := m.getColTextAudit()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetTextAuditList(ctx *gin.Context, id string) (*dbstruct.TextAudit, error) {
	textaudit := &dbstruct.TextAudit{}
	col := m.getColTextAudit()
	query := qmgo.M{
		"_id":      id,
		"del_flag": 0,
	}
	err := col.Find(ctx, query).One(&textaudit)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return nil, err
	}
	return textaudit, err
}

func (m *Mongo) GetTextAuditListByIds(ctx *gin.Context, ids []string) ([]*dbstruct.TextAudit, error) {
	list := make([]*dbstruct.TextAudit, 0)
	col := m.getColTextAudit()
	query := qmgo.M{
		"_id": bson.M{
			"$in": ids,
		},
		"del_flag": 0,
	}
	err := col.Find(ctx, query).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateTextAuditByIds(ctx *gin.Context, textaudit *dbstruct.TextAudit, ids []string) error {
	col := m.getColTextAudit()
	set := util.EntityToM(textaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) UpdateTextAuditByBatchId(ctx *gin.Context, batchId string, textaudit *dbstruct.TextAudit) error {
	col := m.getColTextAudit()
	set := util.EntityToM(textaudit)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"batch_id": batchId,
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

// 文字审核任务相关
func (m *Mongo) CreateTextAuditTask(ctx *gin.Context, textaudittask *dbstruct.TextAuditTask) error {
	col := m.getColTextAuditTask()
	_, err := col.InsertOne(ctx, textaudittask)
	return err
}

func (m *Mongo) UpdateTextAuditTask(ctx *gin.Context, textaudittask *dbstruct.TextAuditTask) error {
	col := m.getColTextAuditTask()
	set := util.EntityToM(textaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	err := col.UpdateId(ctx, textaudittask.Id, up)
	return err
}

func (m *Mongo) DeleteTextAuditTask(ctx *gin.Context, id string) error {
	col := m.getColTextAuditTask()
	update := qmgo.M{
		"$set": qmgo.M{
			"del_flag": 1,
		},
	}
	err := col.UpdateId(ctx, id, update)
	return err
}

func (m *Mongo) GetTextAuditTaskList(ctx *gin.Context, req *textaudittaskproto.OpListReq) ([]*dbstruct.TextAuditTask, error) {
	list := make([]*dbstruct.TextAuditTask, 0)
	col := m.getColTextAuditTask()
	query := qmgo.M{
		"del_flag": 0,
	}
	if req.RouteUrl != nil {
		query["route_url"] = util.DerefString(req.RouteUrl)
	}
	if req.AssociativeDatabase != nil {
		query["associative_data_base"] = util.DerefString(req.AssociativeDatabase)
	}
	if req.AssociativeTableName != nil {
		query["associative_tabel_name"] = util.DerefString(req.AssociativeTableName)
	}
	if req.AssociativeTableId != nil {
		query["associative_tabel_id"] = util.DerefInt64(req.AssociativeTableId)
	}
	if req.AssociativeTableColumn != nil {
		query["associative_tabel_column"] = util.DerefString(req.AssociativeTableColumn)
	}
	if req.BatchId != nil {
		query["batch_id"] = util.DerefString(req.BatchId)
	}
	if req.Status != nil {
		query["status"] = util.DerefInt64(req.Status)
	}
	err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
	if err == qmgo.ErrNoSuchDocuments {
		err = nil
		return list, err
	}
	return list, err
}

func (m *Mongo) UpdateTextAuditTaskByBatchId(ctx *gin.Context, batchId string, textaudittask *dbstruct.TextAuditTask) error {
	col := m.getColTextAuditTask()
	set := util.EntityToM(textaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"batch_id": batchId,
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}

func (m *Mongo) UpdateTextAuditTaskByIds(ctx *gin.Context, textaudittask *dbstruct.TextAuditTask, ids []string) error {
	col := m.getColTextAuditTask()
	set := util.EntityToM(textaudittask)
	set["ut"] = time.Now().Unix()
	up := qmgo.M{
		"$set": set,
	}
	filter := qmgo.M{
		"_id": qmgo.M{
			"$in": ids,
		},
	}
	_, err := col.UpdateAll(ctx, filter, up)
	return err
}