package model

import (
	"time"

	"github.com/shopspring/decimal"
	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
	"gogs.daxia.dev/huanan/pkg.daxia.dev/db"
	"gorm.io/gorm"
)

type GameOrder struct {
	gorm.Model

	UserID     uint            `gorm:"int; comment:用户ID"`
	RoomID     uint            `gorm:"int; comment:房间ID"`
	Issue      string          `gorm:"varchar(40); comment:期号"`
	OpenNumber string          `gorm:"varchar(40); comment:开奖号码"`
	BaseAmount decimal.Decimal `gorm:"comment:底注金额"`
	IsDraw     int             `gorm:"comment:是否开奖, 1: 开奖, 0: 未开奖"`
	DrawTime   *time.Time      `gorm:"comment:开奖时间"`
	IsMaster   int             `gorm:"comment:抢庄牛牛才有，是否为庄, 1: 庄, 0: 闲"`
	MasterMul  int             `gorm:"default:0; comment:抢庄倍数"`
	Mul        int             `gorm:"default:1; comment:下注倍数"`
	IsWin      int             `gorm:"comment:1: 赢, 2: 输, 3: 退回, 0: 未计算"`
	WinAmount  decimal.Decimal `gorm:"comment:奖金"`
	BetIP      string          `gorm:"comment:投注IP"`
	GameID     int             `gorm:"int; comment:游戏ID"`
}

func (GameOrder) TableName() string {
	return viper.GetString("table_prefix") + "game_nn"
}

func (p GameOrder) Init() error {
	if db.GetDB().Migrator().HasTable(p) {
		return nil
	}
	if err := db.GetDB().Migrator().CreateTable(p); err != nil {
		return err
	}

	return nil
}

func (p GameOrder) GetOrderListByIssue(issue string) ([]GameOrder, error) {
	gameID := viper.GetInt32("game_id")
	resultList := make([]GameOrder, 0)
	err := db.GetDB().Model(p).Where("issue = ? and game_id = ?", issue, gameID).Scan(&resultList).Error
	if err != nil {
		logrus.Error(err)
		return nil, err
	}

	return resultList, nil
}

func (p GameOrder) GetUnDrawOrderByIssue(issue string) ([]GameOrder, error) {
	gameID := viper.GetInt32("game_id")
	gameOrderModelList := make([]GameOrder, 0)
	err := db.GetDB().Model(p).Where("is_draw = ? and issue = ? and game_id = ?", 0, issue, gameID).Scan(&gameOrderModelList).Error
	if err != nil {
		logrus.Error(err)
		return nil, err
	}

	return gameOrderModelList, nil
}

func (p GameOrder) GetUserOrderListOpenedByIssue(issue string) ([]GameOrder, error) {
	gameID := viper.GetInt32("game_id")

	gameOrderModelList := make([]GameOrder, 0)
	err := db.GetDB().Model(p).Where("is_draw = 1 and issue = ? and game_id = ?", issue, gameID).
		Scan(&gameOrderModelList).Error
	if err != nil {
		logrus.Error(err)
		return nil, err
	}

	return gameOrderModelList, nil
}

func (p GameOrder) GetUserBetAmountByNumber(tx *gorm.DB, userID uint32, issue string, playType, pos, number string) (string, error) {
	var err error

	gameID := viper.GetInt32("game_id")

	type Info struct {
		UserID int
		Total  decimal.Decimal
	}

	infoModel := Info{}
	err = tx.Model(p).Where("issue = ? and user_id = ? and play_type = ? and pos = ? and number = ? and game_id = ?",
		issue, userID, playType, pos, number, gameID).
		Select("user_id, sum(amount) as total").
		First(&infoModel).
		Error

	if err != nil {
		logrus.Error(err)
		return "", nil
	}

	return infoModel.Total.StringFixed(2), nil
}

func (p GameOrder) GetUserBetCount(userID uint32, issue string, playType, pos string) (int, error) {
	var err error

	gameID := viper.GetInt32("game_id")

	type Info struct {
		Total int
	}

	infoModel := Info{}
	err = db.GetDB().Model(p).Where("issue = ? and user_id = ? and play_type = ? and pos = ? and game_id = ?",
		issue, userID, playType, pos, gameID).
		Select("count(*) as total").
		First(&infoModel).
		Error

	if err != nil {
		logrus.Error(err)
		return 0, nil
	}

	return infoModel.Total, nil
}

func (p GameOrder) GetUserBetCountByTx(tx *gorm.DB, userID uint32, issue string, playType, pos string) (int, error) {
	var err error

	gameID := viper.GetInt32("game_id")

	type Info struct {
		Total int
	}

	infoModel := Info{}
	err = tx.Model(p).Where("issue = ? and user_id = ? and play_type = ? and pos = ? and game_id = ?",
		issue, userID, playType, pos, gameID).
		Select("count(*) as total").
		First(&infoModel).
		Error

	if err != nil {
		logrus.Error(err)
		return 0, nil
	}

	return infoModel.Total, nil
}

//投注了多个号码
func (p GameOrder) GetUserBetTypeCountByTx(tx *gorm.DB, userID uint32, issue string, playType string) (int, error) {
	var err error

	gameID := viper.GetInt32("game_id")

	type Info struct {
		Total int
	}

	infoModel := Info{}
	err = tx.Model(p).Where("issue = ? and user_id = ? and play_type = ? and game_id = ?",
		issue, userID, playType, gameID).
		Select("count(DISTINCT number) as total").
		First(&infoModel).
		Error

	if err != nil {
		logrus.Error(err)
		return 0, nil
	}

	return infoModel.Total, nil
}

func (p GameOrder) GetListByIssue(issueStr string, userID int32) ([]GameOrder, error) {
	gameID := viper.GetInt32("game_id")
	gameOrderModelList := make([]GameOrder, 0)
	err := db.GetDB().Model(p).Where("issue = ? and user_id = ? and game_id = ?", issueStr, userID, gameID).
		Scan(&gameOrderModelList).Error

	return gameOrderModelList, err
}

func (p GameOrder) SetNewOdd(id uint, newOdd float64) error {
	err := db.GetDB().Model(p).Where("id = ?", id).Update("odds", newOdd).Error
	if err != nil {
		logrus.Error(err)
		return err
	}

	return err
}
