package recharge_t_mall_game_account

import (
	"context"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/model"
	"kami/internal/model/do"
	"kami/internal/model/entity"
	"kami/internal/service"
	"kami/utility/config"
	"kami/utility/utils"

	"github.com/duke-git/lancet/v2/pointer"
	"github.com/duke-git/lancet/v2/random"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/grand"
	"github.com/gogf/gf/v2/util/gutil"
)

func init() {
	service.RegisterRechargeTMallGameAccount(New())
}

func New() *sRechargeTMallGameAccount {
	return &sRechargeTMallGameAccount{}
}

type sRechargeTMallGameAccount struct{}

func (a *sRechargeTMallGameAccount) generateAccountNumber(ctx context.Context) (accountNumber string) {
	//随机生成一个电子邮箱，电子邮箱由大小写字母和数字组成
	prefix := grand.S(random.RandInt(4, 12))
	suffix := grand.Letters(random.RandInt(3, 8))
	return prefix + "@" + suffix + ".com"
}

func (a *sRechargeTMallGameAccount) Add(ctx context.Context, input *model.RechargeTMallGameAccountAddInput) (err error) {
	err = config.GetDatabaseV1().Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		accountList := g.Array{}
		i := 0
		//创建不重复账号
		for {
			accountNumber := a.generateAccountNumber(ctx)
			if !a.CheckAccountNumberExists(ctx, accountNumber, tx) {
				accountList = append(accountList, &do.V1RechargeTMallAccount{
					Id:            utils.GenerateRandomUUID(),
					Status:        consts.RechargeTMallGameAccountStatusEnable,
					AccountNumber: accountNumber,
					Balance:       0,
				})
				i++
			}
			if i >= input.Count {
				break
			}
		}
		_, err2 := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1()).TX(tx).Data(accountList).Insert()
		return err2
	})
	return err
}

// CheckAccountNumberExists 判断当前账户是否存在
func (a *sRechargeTMallGameAccount) CheckAccountNumberExists(ctx context.Context, accountNumber string, tx gdb.TX) bool {
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	count, err := m.Where(dao.V1RechargeTMallAccount.Columns().AccountNumber, accountNumber).Count()
	if err != nil || count == 0 {
		return false
	}
	return true
}

// CheckAccountNumberNormal 判断当前账户是否可用
func (a *sRechargeTMallGameAccount) CheckAccountNumberNormal(ctx context.Context, accountNumber string, tx gdb.TX) bool {
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1RechargeTMallAccount.Columns().Status, consts.RechargeTMallGameAccountStatusEnable)
	if tx != nil {
		m = m.TX(tx)
	}
	count, err := m.Where(dao.V1RechargeTMallAccount.Columns().AccountNumber, accountNumber).Count()
	if err != nil || count == 0 {
		return false
	}
	return true
}

func (a *sRechargeTMallGameAccount) List(ctx context.Context, input *model.RechargeTMallGameAccountListInput) (total int, data []entity.V1RechargeTMallAccount, err error) {
	total = 0
	data = make([]entity.V1RechargeTMallAccount, 0)
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1()).Page(input.Current, input.PageSize)
	if input.AccountNumber != "" {
		m = m.WhereLike(dao.V1RechargeTMallAccount.Columns().AccountNumber, utils.OrmLike(input.AccountNumber))
	}
	err = m.ScanAndCount(&data, &total, false)
	return
}

// Toggle 改变账号状态
func (a *sRechargeTMallGameAccount) Toggle(ctx context.Context, input *model.RechargeTMallGameAccountToggleInput) (err error) {

	return config.GetDatabaseV1().Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		data := new(entity.V1RechargeTMallAccount)
		err = dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1()).TX(tx).Where(dao.V1RechargeTMallAccount.Columns().Id, input.ID).Scan(&data)
		if err != nil {
			return err
		}
		status := consts.RechargeTMallGameAccountStatusEnable
		switch data.Status {
		case string(consts.RechargeTMallGameAccountStatusEnable):
			status = consts.RechargeTMallGameAccountStatusDisable
		case string(consts.RechargeTMallGameAccountStatusDisable):
			status = consts.RechargeTMallGameAccountStatusEnable
		}
		_, err = dao.V1RechargeTMallAccount.Ctx(ctx).TX(tx).DB(config.GetDatabaseV1()).
			Where(dao.V1RechargeTMallAccount.Columns().Id, input.ID).
			Update(do.V1RechargeTMallAccount{Status: status})
		return err
	})
}

// GetOne 根据id获取账号信息
func (a *sRechargeTMallGameAccount) GetOne(ctx context.Context, id, accountNumber string) (data *entity.V1RechargeTMallAccount, err error) {
	data = new(entity.V1RechargeTMallAccount)
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	if id != "" {
		m = m.Where(dao.V1RechargeTMallAccount.Columns().Id, id)
	}
	if accountNumber != "" {
		m = m.Where(dao.V1RechargeTMallAccount.Columns().AccountNumber, accountNumber)
	}
	err = m.Scan(&data)
	return
}

// GetRandomOne 随机获取一个账号,如果没有新的账号，就创建一个新账号
func (a *sRechargeTMallGameAccount) GetRandomOne(ctx context.Context, excludeAccountNumber []string) (accountNumber string, err error) {
	accountNumber = ""
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	err = m.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		//获取所有正在创建状态的账号
		accountNumberList := garray.NewStrArray()
		accountInfo, err2 := service.RechargeTMallGameOrder().GetAllCreatedAccount(ctx, tx)
		if err2 != nil {
			return err2
		}
		for _, info := range accountInfo {
			accountNumberList.Append(info.AccountNumber)
		}
		//添加缓存中的账号
		accountNumberList.Append(excludeAccountNumber...)
		data := new(entity.V1RechargeTMallAccount)
		total := 0
		err = m.TX(tx).Where(dao.V1RechargeTMallAccount.Columns().Status, consts.RechargeTMallGameAccountStatusEnable).
			WhereNotIn(dao.V1RechargeTMallAccount.Columns().AccountNumber, accountNumberList.Unique().Slice()).
			OrderRandom().
			ScanAndCount(&data, &total, false)
		if total <= 10 {
			gutil.Go(context.WithoutCancel(ctx), func(ctx context.Context) {
				for i := 0; i < 10*10; i++ {
					_, _ = a.AddRandomOne(ctx, nil)
				}
			}, nil)
		}
		err = utils.HandleNoRowsError(err)
		if !pointer.IsNil(data) && data.Id != "" {
			accountNumber = data.AccountNumber
			return nil
		}
		if phoneNumber, err3 := a.AddRandomOne(ctx, tx); err3 == nil {
			accountNumber = phoneNumber
			return nil
		} else if err3 != nil {
			return err3
		}
		return nil
	})
	return
}

// AddRandomOne 添加一个随机账号
func (a *sRechargeTMallGameAccount) AddRandomOne(ctx context.Context, tx gdb.TX) (phoneNumber string, err error) {
	for {
		phoneNumber = a.generateAccountNumber(ctx)
		data, _ := a.GetOne(ctx, "", phoneNumber)
		if data == nil || data.Id == "" {
			break
		}
	}
	m := dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	_, err = m.Data(do.V1RechargeTMallAccount{
		Id:            utils.GenerateRandomUUID(),
		Status:        consts.RechargeTMallGameAccountStatusEnable,
		AccountNumber: phoneNumber,
		Balance:       0,
	}).Insert()
	return
}

// DeleteOne 删除账户
func (a *sRechargeTMallGameAccount) DeleteOne(ctx context.Context, id string) (err error) {
	_, err = dao.V1RechargeTMallAccount.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1RechargeTMallAccount.Columns().Id, id).Delete()
	return
}
