package module

import (
	"context"
	"fmt"
	jsoniter "github.com/json-iterator/go"
	"github.com/mhaya/game/game_cluster/internal/constant"
	"github.com/mhaya/game/game_cluster/internal/mdb"
	"github.com/mhaya/game/game_cluster/internal/mdb/models"
	"github.com/mhaya/game/game_cluster/internal/token"
	clog "github.com/mhaya/logger"
	"github.com/mhaya/net/parser/simple"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"log"
	"time"
)

type (
	ActorSaves struct {
		simple.ActorBase
	}
)

func (p *ActorSaves) AliasID() string {
	return "save_dbs"
}

func (p *ActorSaves) OnInit() {
	p.Timer().Add(60*time.Second, p.saveAccountDB1)
	p.Timer().Add(60*time.Second, p.savePlayerDB1)
}

func (p *ActorSaves) saveAccountDB1() {
	go p.saveAccountDB()
}

func (p *ActorSaves) savePlayerDB1() {
	go p.savePlayerDB()
}

func (p *ActorSaves) saveAccountDB() {
	key := 0
	newKey := 0
	bulkUpdOps := []mongo.WriteModel{}
	bulkInsAccountOps := []mongo.WriteModel{}
	bulkInsPlayerOps := []mongo.WriteModel{}
	updAccount := []string{}
	insAccount := []string{}
	insPlayer := []string{}
	ctx := context.Background()
	newAccounts := mdb.RDB.HGetAll(ctx, constant.NewAccounts).Val()
	for k, v := range newAccounts {
		var account models.Account
		if v == "1" {
			if newKey < 10000 {
				acc, _ := mdb.RDB.Get(ctx, fmt.Sprintf("%v:%v", constant.CNameAccount, k)).Bytes()
				if len(acc) > 0 {
					err := jsoniter.Unmarshal(acc, &account)
					if err != nil {
						continue
					}
				}
				if account.OpenId != "" {
					bulkInsAccountOps = append(bulkInsAccountOps, mongo.NewInsertOneModel().SetDocument(&account))
					player := models.NewPlayer(token.New(2, account.OpenId, account.UserName, "", "", ""))
					bulkInsPlayerOps = append(bulkInsPlayerOps, mongo.NewInsertOneModel().SetDocument(&player))
					insAccount = append(insAccount, account.OpenId)
					insPlayer = append(insPlayer, account.OpenId)
				}
			}
			newKey++
		} else {
			if key < 10000 {
				acc, _ := mdb.RDB.Get(ctx, fmt.Sprintf("%v:%v", constant.CNameAccount, k)).Bytes()
				if len(acc) > 0 {
					err := jsoniter.Unmarshal(acc, &account)
					if err != nil {
						continue
					}
				}
				filter := bson.M{"openId": account.OpenId}
				update := bson.M{"$set": &account}
				bulkUpdOps = append(bulkUpdOps, mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update))
				updAccount = append(updAccount, account.OpenId)
				key++
			}
		}
		if newKey > 10000 || key > 10000 {
			break
		}
	}
	if len(bulkUpdOps) > 0 {
		_, err := mdb.MDB.Collection(constant.CNameAccount).BulkWrite(context.Background(), bulkUpdOps)
		if err != nil {
			clog.Fatalf("saveAccountDB Bulk write failed: %v", err)
		}
		mdb.RDB.HDel(ctx, constant.NewAccounts, updAccount...)
	}

	if len(bulkInsAccountOps) > 0 {
		_, err := mdb.MDB.Collection(constant.CNameAccount).BulkWrite(context.Background(), bulkInsAccountOps)
		if err != nil {
			log.Fatalf("Bulk write failed: %v", err)
		}
		mdb.RDB.HDel(ctx, constant.NewAccounts, insAccount...)
	}
	if len(bulkInsPlayerOps) > 0 {
		_, err := mdb.MDB.Collection(constant.CNamePlayer).BulkWrite(context.Background(), bulkInsPlayerOps)
		if err != nil {
			log.Fatalf("Bulk write failed: %v", err)
		}
		mdb.RDB.HDel(ctx, constant.NewPlayers, insPlayer...)
	}

}

func (p *ActorSaves) savePlayerDB() {
	key := 0
	bulkUpdOps := []mongo.WriteModel{}
	ctx := context.Background()
	newPlayers := mdb.RDB.HGetAll(ctx, constant.NewPlayers).Val()
	updPlayer := []string{}
	for k, _ := range newPlayers {
		if key > 10000 {
			break
		}
		var player models.Player
		acc, _ := mdb.RDB.Get(ctx, fmt.Sprintf("%v:%v", constant.CNamePlayer, k)).Bytes()
		if len(acc) > 0 {
			err := jsoniter.Unmarshal(acc, &player)
			if err != nil {
				continue
			}
		}
		filter := bson.M{"openId": player.OpenId}
		update := bson.M{"$set": &player}
		bulkUpdOps = append(bulkUpdOps, mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update))
		updPlayer = append(updPlayer, player.OpenId)
	}
	if len(bulkUpdOps) > 0 {
		_, err := mdb.MDB.Collection(constant.CNamePlayer).BulkWrite(context.Background(), bulkUpdOps)
		if err != nil {
			clog.Fatalf("saveAccountDB Bulk write failed: %v", err)
		}
		mdb.RDB.HDel(ctx, constant.NewPlayers, updPlayer...)
	}
}

/*func (p *ActorSaves) OnFindChild(msg *cfacade.Message) (cfacade.IActor, bool) {
	// 动态创建 player child actor
	childID := msg.TargetPath().ChildID
	childActor, err := p.Child().Create(childID, &{
		isOnline: false,
	})

	if err != nil {
		return nil, false
	}

	return childActor, true
}*/

func (p *ActorSaves) OnStop() {
	clog.Infof("ActorSaves stop")
}
