package server

import (
	"encoding/json"
	"game/common/model/user"
	"game/common/proto/pb"
	"game/server/db/operation"
	"github.com/fox/fox/ipb"
	"github.com/fox/fox/ksync"
	"github.com/fox/fox/log"
)

// 获取帐号
func (s *DbService) onGetUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserAccount](iMsg, func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
		return operation.NewUserAccountOp().GetUserAccount(us.Username)
	})
	return iMsg
}

func (s *DbService) onGetUserAccountById(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserAccount](iMsg, func(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
		return operation.NewUserAccountOp().Find(us.ID)
	})
	return iMsg
}

// 创建帐号
func (s *DbService) onCreateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserAccount](iMsg, operation.NewUserAccountOp().CreateUserAccount)
	return iMsg
}

type result[T any] struct {
	ret T
}

// 装饰器
// 返回值存在iMsg.Msg中
func operationDb[T any](iMsg *ipb.InternalMsg, operation func(table *T) (*T, pb.ErrCode)) {
	t := result[T]{}
	err := json.Unmarshal(iMsg.Msg, &t.ret)
	if err != nil {
		log.ErrorF("error unmarshalling user account %v", err)
		iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
		return
	}
	table, code := operation(&t.ret)
	if code != pb.ErrCode_OK {
		iMsg.RpcCode = int32(code)
		return
	}
	iMsg.Msg, err = json.Marshal(table)
	if err != nil {
		log.ErrorF("error marshalling user account %v", err)
		iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
		return
	}
	//log.DebugF("iMsg.Msg:%v", string(iMsg.Msg))
	return
}

// 修改密码
func (s *DbService) onUpdateUserAccount(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserAccount](iMsg, operation.NewUserAccountOp().UpdateUserPassword)
	return iMsg
}

// 日志操作无需返回值
func (s *DbService) onLogUserAccountLogin(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserLoginLog](iMsg, func(us *user.UserLoginLog) (*user.UserLoginLog, pb.ErrCode) {
		operation.NewUserAccountOp().RecordLoginLog(us)
		return nil, pb.ErrCode_OK
	})
	return iMsg
}

// 获取用户数据，没有则创建用户数据及用户资源
func (s *DbService) onGetUserByAccountId(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.User](iMsg, func(us *user.User) (*user.User, pb.ErrCode) {
		userOp := operation.NewUserOp()
		us2, code := userOp.GetUserByAccountId(us.AccountId)
		if code != pb.ErrCode_OK {
			if us2, code = userOp.Create(us); code == pb.ErrCode_OK {
				operation.NewUserResourcesOp().Create(&user.UserResources{UID: us2.ID})
			}
		}
		return us2, pb.ErrCode_OK
	})
	return iMsg
}

// 获取用户数据
func (s *DbService) onGetUserByUid(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.User](iMsg, func(us *user.User) (*user.User, pb.ErrCode) {
		return operation.NewUserOp().Find(us.ID)
	})
	return iMsg
}

// 获取用户资源数据，没有则创建
func (s *DbService) onGetUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.UserResources](iMsg, func(res *user.UserResources) (*user.UserResources, pb.ErrCode) {
		resOp := operation.NewUserResourcesOp()
		if us1, code := resOp.Find(res.UID); code != pb.ErrCode_OK {
			return resOp.Create(res)
		} else {
			return us1, code
		}
	})
	return iMsg
}

// 添加用户资源，负数为减少。资源不能为负数
func (s *DbService) onAddUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	addUserRes := &user.AddUserRes{}
	err := json.Unmarshal(iMsg.Msg, addUserRes)
	if err != nil {
		log.ErrorF("err:%v unmarshalling user resources %v", err, string(iMsg.Msg))
		iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
		return iMsg
	}
	// 获取资源的值并检查够不够操作
	resOp := operation.NewUserResourcesOp()
	var resNames []string
	for name := range addUserRes.AddRes {
		resNames = append(resNames, name)
	}
	userRes, code := resOp.GetInt(iMsg.UserId, resNames)
	if code != pb.ErrCode_OK {
		iMsg.RpcCode = int32(code)
		return iMsg
	}
	for resName, resValue := range userRes {
		// 如果add为负数则为扣除，
		if addUserRes.AddRes[resName]+resValue < 1 {
			iMsg.RpcCode = int32(pb.ErrCode_GoldNotEnough)
			return iMsg
		}
	}

	rets, code := resOp.AddInt(iMsg.UserId, addUserRes.AddRes)
	if code != pb.ErrCode_OK {
		iMsg.RpcCode = int32(code)
		return iMsg
	}
	iMsg.Msg, err = json.Marshal(rets)
	if err != nil {
		log.ErrorF("error marshalling user account %v", err)
		iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
		return iMsg
	}
	logOp := operation.NewUserResourcesLogOp()
	ksync.GoSafe(func() {
		for resName, resAfterValue := range rets {
			resAddValue := addUserRes.AddRes[resName]
			logOp.Create(&user.UserResourcesLog{
				UID:           iMsg.UserId,
				ResName:       resName,
				ResAddValue:   resAddValue,
				ResAfterValue: resAfterValue,
				GameId:        addUserRes.GameId,
				GameNo:        addUserRes.GameNo,
				Reason:        addUserRes.Reason,
			})
		}
	}, nil)

	return iMsg
}

// 获取用户数据
func (s *DbService) onGetGameUser(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	operationDb[user.GameUser](iMsg, func(gameUser *user.GameUser) (*user.GameUser, pb.ErrCode) {
		us, code := operation.NewUserOp().Find(gameUser.ID)
		if code != pb.ErrCode_OK {
			return nil, code
		}
		res, code1 := operation.NewUserResourcesOp().Find(gameUser.ID)
		if code1 != pb.ErrCode_OK {
			return nil, code
		}
		gameUser.User = *us
		gameUser.UserResources = *res
		return gameUser, pb.ErrCode_OK
	})
	return iMsg
}

// 保存游戏对局日志
func (s *DbService) onSaveGameRecordLog(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	// 日志，没必要阻塞主协程
	ksync.GoSafe(func() {
		operationDb[user.GameRecordLog](iMsg, func(record *user.GameRecordLog) (*user.GameRecordLog, pb.ErrCode) {
			_, code := operation.NewGameRecordLogOp().Create(record)
			return nil, code
		})
	}, nil)
	return iMsg
}

// 保存游戏对局日志
func (s *DbService) onSaveUserRecordLog(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
	// 日志，没必要阻塞主协程
	ksync.GoSafe(func() {
		operationDb[user.UserRecordLog](iMsg, func(record *user.UserRecordLog) (*user.UserRecordLog, pb.ErrCode) {
			_, code := operation.NewUserRecordLogOp().Create(record)
			return nil, code
		})
	}, nil)
	return iMsg
}
