package qznn

import (
	"fmt"

	"github.com/shopspring/decimal"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
	"nn.daxia.dev/model"
)

type PayoutInfo struct {
	PlayerID int32
	Amount   decimal.Decimal
	IsMaster bool
}

func (p *Game) payout(tx *gorm.DB, roomBaseAmount decimal.Decimal, roomID int32) (map[int32]PayoutInfo, error) {
	payoutInfoMap := map[int32]PayoutInfo{}

	room := p.RoomMap[roomID]
	userIDList, err := p.getRoomUserIDListWithStatus(roomID, PlayerStatusOpen)
	if err != nil {
		logrus.Error(err)
		return nil, err
	}

	//获取庄家的牌
	var masterPlayerItem Player
	for _, userID := range userIDList {
		playerItem := p.PlayerMap[userID]
		if !playerItem.IsMaster {
			continue
		}

		masterPlayerItem = playerItem
		break
	}

	masterCardList := GetNNCardList(masterPlayerItem.CardList)
	masterTotalWinAmount := decimal.NewFromInt(0)
	winTotal := decimal.NewFromInt(0)
	loseToMaster := decimal.NewFromInt(0)

	for _, userID := range userIDList {
		if userID == masterPlayerItem.ID {
			continue
		}

		userItem, exists := p.PlayerMap[userID]
		if !exists {
			logrus.Error("not exist:", userID)
			continue
		}

		var winAmount decimal.Decimal
		userCardList := GetNNCardList(userItem.CardList)
		masterWin, isEqual, cardLevel := WinLevel(masterCardList, userCardList)
		if !masterWin {
			_, _, cardLevel = WinLevel(userCardList, masterCardList)
		}

		userModel, err := model.User{}.GetUserByIDTx(tx, uint32(userID))
		if err != nil {
			logrus.Error(err)
			return nil, err
		}

		if isEqual {
			winAmount = decimal.NewFromInt(0)
		} else {
			if !masterWin {

				//赢庄家
				winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(int64(cardLevel)))
			} else {

				//输给庄家
				winAmount = room.BaseAmount.Mul(decimal.NewFromInt(int64(masterPlayerItem.MasterMul))).Mul(decimal.NewFromInt(int64(userItem.Mul))).Mul(decimal.NewFromInt(int64(cardLevel))).Mul(decimal.NewFromInt(-1))
			}
		}

		if room.RoomType == int32(model.RoomTypeFree) {
			if winAmount.GreaterThan(decimal.Zero) {
				if winAmount.GreaterThan(userModel.CreditsQZNN) {
					winAmount = userModel.CreditsQZNN
				}
			} else {
				if winAmount.Abs().GreaterThan(userModel.CreditsQZNN) {
					winAmount = userModel.CreditsQZNN.Mul(decimal.NewFromInt(-1))
				}
			}

			payoutInfoMap[userID] = PayoutInfo{
				PlayerID: userID,
				Amount:   winAmount,
				IsMaster: false,
			}
		} else {
			if winAmount.GreaterThan(decimal.Zero) {
				if winAmount.GreaterThan(userModel.BalanceQZNN) {
					winAmount = userModel.BalanceQZNN
				}
			} else {
				if winAmount.Abs().GreaterThan(userModel.BalanceQZNN) {
					winAmount = userModel.BalanceQZNN.Mul(decimal.NewFromInt(-1))
				}
			}

			payoutInfoMap[userID] = PayoutInfo{
				PlayerID: userID,
				Amount:   winAmount,
				IsMaster: false,
			}
		}

		if winAmount.GreaterThan(decimal.Zero) {
			winTotal = winTotal.Add(winAmount)
		} else {
			loseToMaster = loseToMaster.Add(winAmount.Abs())
		}

		masterTotalWinAmount = masterTotalWinAmount.Add(winAmount.Mul(decimal.NewFromInt(-1)))
	}

	fmt.Printf("masterPlayerItem:%v", masterPlayerItem)

	masterUserModel := model.User{}
	err = tx.Model(model.User{}).Where("id = ?", masterPlayerItem.ID).First(&masterUserModel).Error
	if err != nil {
		logrus.Error(err)
		return nil, err
	}

	needFix := false
	if room.RoomType == int32(model.RoomTypeFree) {
		if masterTotalWinAmount.LessThan(decimal.Zero) {
			if masterTotalWinAmount.Abs().GreaterThan(masterUserModel.CreditsQZNN.Add(loseToMaster)) {
				masterTotalWinAmount = masterUserModel.CreditsQZNN.Mul(decimal.NewFromInt(-1))
				needFix = true
			}
		}
	} else {
		if masterTotalWinAmount.LessThan(decimal.Zero) {
			if masterTotalWinAmount.Abs().GreaterThan(masterUserModel.BalanceQZNN.Add(loseToMaster)) {
				masterTotalWinAmount = masterUserModel.BalanceQZNN.Mul(decimal.NewFromInt(-1))
				needFix = true
			}
		}
	}

	if needFix {
		for userID, payoutInfo := range payoutInfoMap {
			prevAmount := payoutInfo.Amount
			if prevAmount.LessThan(decimal.Zero) {
				continue
			}

			payoutInfo.Amount = payoutInfo.Amount.Div(winTotal).Mul(masterTotalWinAmount.Abs().Add(loseToMaster))
			logrus.Infof("amount:%v, win_total:%v, new_amont:%v", prevAmount, winTotal, payoutInfo.Amount)

			if payoutInfo.Amount.GreaterThan(decimal.NewFromInt(3000)) {
				logrus.Fatal("金额异常:", payoutInfo)
			}

			payoutInfoMap[userID] = payoutInfo
		}
	}

	payoutInfoMap[masterPlayerItem.ID] = PayoutInfo{
		PlayerID: masterPlayerItem.ID,
		Amount:   masterTotalWinAmount,
		IsMaster: true,
	}

	//佣金
	for userID, payoutInfo := range payoutInfoMap {
		amount := payoutInfo.Amount
		if amount.LessThanOrEqual(decimal.Zero) {
			continue
		}

		payoutInfo.Amount = amount.Sub(amount.Mul(decimal.NewFromFloat(0.05)))
		payoutInfoMap[userID] = payoutInfo
	}

	return payoutInfoMap, nil
}
