package model

import (
	"errors"

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

type User struct {
	ID            uint            `gorm:"primarykey"`
	Pid           uint            `gorm:"varchar(40); comment:'父ID'"`
	Name          string          `gorm:"varchar(40); comment:'名称'"`
	Nickname      string          `gorm:"varchar(40); comment:'nickname'"`
	Mobile        string          `gorm:"varchar(40); comment:'手机号'"`
	AccountType   int             `gorm:"int; comment:'账号类型'"` //0:普通用户, 1:代理
	Status        int             `gorm:"int; comment:'状态0:禁用,1:启用'"`
	Balance       decimal.Decimal `sql:"type:decimal(16.2)"`
	FZBalance     decimal.Decimal `sql:"type:decimal(16.2)"`
	HeadImg       string          `gorm:"varchar(40); comment:'头像'"`
	Token         string          `gorm:"varchar(40); comment:'token'"`
	City          string          `gorm:"varchar(40); comment:'城市'"`
	ParentTree    string          `gorm:"varchar(40); comment:'目录树'"`
	ParentTreeStr string          `gorm:"varchar(40); comment:'父节点'"`
}

func (User) TableName() string {
	return "users"
}

func (p User) Init() error {
	//var err error

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

	return nil
}

func (p User) GetUserModelByID(id uint) (*User, error) {
	userModel := User{}
	err := db.GetDB().Model(p).Where("id = ?", id).First(&userModel).Error
	return &userModel, err
}

func (p User) UpdateUserNicknameByID(id uint, nickname string) error {
	err := db.GetDB().Model(p).Where("id = ?", id).Update("nickname", nickname).Error
	return err
}

func (p User) UpdateHeadImgByID(id uint, headImg string) error {
	err := db.GetDB().Model(p).Where("id = ?", id).Update("head_img", headImg).Error
	return err
}

func (p User) UpdateUserNicknameAndPhoneByID(id uint, nickname, phone string) error {
	err := db.GetDB().Model(p).Where("id = ?", id).Updates(map[string]interface{}{
		"nickname": nickname,
		"mobile":   phone,
	}).Error

	return err
}

func (p *User) GetUserByID(userID uint32) error {
	var err error

	err = db.GetDB().
		Model(p).
		Where("status = 1 and id = ?", userID).First(p).Error

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

	return nil
}

func (p User) GetUserByIDTx(tx *gorm.DB, userID uint32) (*User, error) {
	var err error

	userModel := User{}
	err = tx.
		Model(p).
		Where("status = 1 and platform_flag = 1").
		Where("id = ?", userID).First(&userModel).Error

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

	return &userModel, nil
}

func (p User) GetUserByIDList(userIDList []uint32) ([]User, error) {
	var err error

	userModelList := make([]User, 0)
	err = db.GetDB().Table("users").Where("id in ?", userIDList).Scan(&userModelList).Error
	if err != nil {
		logrus.Error(err, userIDList)
		return nil, err
	}

	return userModelList, nil
}

func (p *User) TokenIsValid(userToken string) (bool, error) {
	var err error

	err = db.GetDB().Table("users").Where("token = ?", userToken).First(p).Error
	if err != nil {
		logrus.Error(err)
		return false, err
	}

	if p.Status != 1 {
		return false, nil
	}

	return true, nil
}

func (p User) IncBotUserAmount(userID uint32, amount *decimal.Decimal) error {
	updateItem := db.GetDB().Model(p).
		Where("status = 1 and platform_flag = 1 and parent_tree_str = 'robot'").
		Where("id = ?", userID).
		Update("balance", gorm.Expr("balance + ?", amount))

	if updateItem.RowsAffected != 1 {
		return errors.New("余额不足")
	}

	return updateItem.Error
}

func (p User) DescBotUserAmount(userID uint32, amount *decimal.Decimal) error {
	updateItem := db.GetDB().Model(p).
		Where("status = 1 and platform_flag = 1  and parent_tree_str = 'robot'").
		Where("id = ? and balance - ? >= 0", userID, amount).
		Update("balance", gorm.Expr("balance - ?", amount))

	if updateItem.RowsAffected != 1 {
		return errors.New("余额不足")
	}

	return updateItem.Error
}
