package service

import (
	"context"
	"entrance-grpc/iam"
	"errors"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/utility/serializer"
	"github.com/sirupsen/logrus"
	"time"

	"golang.org/x/crypto/bcrypt"
)

// User 管理员服务
var User = NewsUser()

type LoginStats struct {
	FailNum int
	BanTs   int64
}

type sUser struct {
	BanIps map[string]*LoginStats
}

func NewsUser() *sUser {
	user := new(sUser)
	user.BanIps = make(map[string]*LoginStats)
	return user
}

// 一次登录，清空错误次数
func (s *sUser) AddSucessNum(ip string) {
	delete(s.BanIps, ip)
}

// 增加错误登录次数，超过10次，不再进行密码验证
func (s *sUser) AddFailNum(ip string) {
	stats, ok := s.BanIps[ip]
	if !ok {
		stats = new(LoginStats)
		s.BanIps[ip] = stats
	}
	if stats.BanTs > 0 {
		return
	}
	if stats.FailNum > 10 {
		curTs := time.Now().Unix()
		stats.BanTs = curTs

		// 清理错误登录
		for k, v := range s.BanIps {
			if v.BanTs+24*60*60 < curTs {
				delete(s.BanIps, k)
			}
		}
		return
	}
	stats.FailNum += 1
}

// 检查是否允许登录
func (s *sUser) CheckLoginAllow(ip string) bool {
	stats, ok := s.BanIps[ip]
	if !ok {
		return true
	}
	cur := time.Now().Unix()

	if stats.BanTs+1*60*60 > cur {
		return false
	}
	stats.BanTs = 0
	stats.FailNum = 0
	return true
}

// GetUser 用ID获取用户
func (s *sUser) GetUser(ID interface{}) (u *model.AdminUser, err error) {
	res, err1 := config.GetIamClient().GetAdminUserByID(context.Background(), &iam.GetAdminUserByIDReq{
		UID: ID.(int64),
	})
	u = new(model.AdminUser)
	if err1 == nil && res.Data != nil {
		u.ID = res.Data.ID
		u.RoleID = int32(res.Data.RoleID)
		u.Status = int32(res.Data.Status)
		u.UserName = res.Data.UserName
		u.Nickname = res.Data.NickName
		u.Avatar = res.Data.Avatar
	} else {
		logrus.Warnf("GetAdminUserByID Err:%+v", err1)
		err = errors.New("获取用户信息失败")
	}
	return u, err
}

// SetPassword 设置密码
func (s *sUser) SetPassword(password string) (string, error) {
	bytes, err := bcrypt.GenerateFromPassword([]byte(password), consts.PassWordCost)
	if err != nil {
		return "", err
	}
	return string(bytes), nil
}

// CheckPassword 校验密码
func (s *sUser) CheckPasswordRight(passwordDigest, password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(passwordDigest), []byte(password))
	return err == nil
}

//func (s *sUser) Login(req forms.UserLoginReq, ip string) serializer.Response {
//	var (
//		u model.AdminUser
//	)
//	if ok := s.CheckLoginAllow(ip); !ok {
//		return serializer.ParamErr("账号已被禁止登录", nil)
//	}
//
//	if err := config.AdminDB.Where("user_name = ?", req.UserName).First(&u).Error; err != nil {
//		s.AddFailNum(ip)
//		logrus.Warnf("sUser %v Login req error %v.", req.UserName, ip)
//		return serializer.ParamErr("账号错误或不存在，请检查", nil)
//	}
//	//p, _ := s.SetPassword(req.Password)
//	//fmt.Println("pass:", p)
//
//	if u.Status != 1 {
//		return serializer.ParamErr("账号已被禁用", nil)
//	}
//
//	if s.CheckPasswordRight(u.PasswordDigest, req.Password) == false {
//		s.AddFailNum(ip)
//		logrus.Warnf("sUser %v Login req error. ip: %v.", req.UserName, ip)
//		return serializer.ParamErr("密码不正确，如忘记了密码请联系管理员！", nil)
//	}
//	s.AddSucessNum(ip)
//
//	//if os.Getenv("GIN_MODE") == "release" && u.UserName == "mojun" {
//	//	return serializer.ParamErr("该账号只允许在测试服登录！", nil)
//	//}
//
//	t := token.GenerateTokenUsingUUID()
//
//	// 记录登录token
//	key := config.GetUserTokenKey(u.ID)
//	config.TokenRedis.HSet(key, t, time.Now().Unix())
//	config.TokenRedis.Expire(key, config.TokenExpireTime)
//
//	tokenKey := config.GetTokenKey(t)
//	user := &token.UserClaims{
//		ID:          u.ID,
//		UserName:    u.UserName,
//		RoleId:      int64(u.RoleID),
//		Avatar:      u.Avatar,
//		Nickname:    u.Nickname,
//		AccessToken: t,
//	}
//	userStr, err := jsoniter.MarshalToString(user)
//	if err != nil {
//		return serializer.Err(1, "", err)
//	}
//	config.TokenRedis.Set(tokenKey, userStr, config.TokenExpireTime)
//
//	return serializer.Suc(forms.UserLoginRes{
//		ID:       u.ID,
//		UserName: u.UserName,
//		Nickname: u.Nickname,
//		Status:   u.Status,
//		Avatar:   u.Avatar,
//		Token:    base64.URLEncoding.EncodeToString([]byte(t)),
//	})
//
//	//t, err := token.GenerateToken(&token.UserClaims{
//	//	ID:       u.ID,
//	//	UserName: u.UserName,
//	//	RoleId:   int64(u.RoleID),
//	//	Avatar:   u.Avatar,
//	//	Nickname: u.Nickname,
//	//})
//	//if err != nil {
//	//	return serializer.ParamErr(err.Error(), nil)
//	//}
//	//return serializer.Suc(forms.UserLoginRes{
//	//	ID:       u.ID,
//	//	UserName: u.UserName,
//	//	Nickname: u.Nickname,
//	//	Status:   u.Status,
//	//	Avatar:   u.Avatar,
//	//	Token:    t,
//	//})
//}

func (s *sUser) Register(req forms.UserRegisterReq) serializer.Response {
	user := model.AdminUser{
		Nickname: req.Nickname,
		UserName: req.UserName,
		Status:   consts.StatusNormal,
	}

	count := int64(0)
	config.DB.Model(&model.AdminUser{}).Where("nickname = ?", req.Nickname).Count(&count)
	if count > 0 {
		return serializer.Response{
			Code: 40001,
			Msg:  "昵称被占用",
		}
	}

	config.DB.Model(&model.AdminUser{}).Where("user_name = ?", req.UserName).Count(&count)
	if count > 0 {
		return serializer.Response{
			Code: 40001,
			Msg:  "用户名已经注册",
		}
	}

	// 加密密码
	password, err := s.SetPassword(req.Password)
	if err != nil {
		return serializer.Err(
			consts.CodeEncryptError,
			"密码加密失败",
			err,
		)
	}

	user.PasswordDigest = password
	if err = config.DB.Create(&user).Error; err != nil {
		return serializer.ParamErr("注册失败", err)
	}

	user.PasswordDigest = ""

	return serializer.Suc(user)
}

//func (s *sUser) List(ctx *gin.Context, req forms.AdminUserListReq) serializer.Response {
//	var (
//		q            = query.Use(config.AdminDB).AdminUser
//		r            = query.Use(config.AdminDB).AdminRole
//		m            = q.WithContext(ctx)
//		offset int64 = 0
//		models forms.UserAccountListRes
//		lists  []*forms.AdminUserListModel
//	)
//
//	m = m.Order(q.ID.Desc())
//
//	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
//
//	count, err := m.Count()
//	if err != nil {
//		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
//	}
//
//	if count > 0 {
//		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
//			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
//		}
//	}
//
//	for _, v := range lists {
//		role, err := r.WithContext(ctx).Where(r.ID.Eq(v.RoleID)).First()
//		v.RoleName = "未绑定角色"
//		if role != nil && err == nil {
//			v.RoleName = role.Name
//		}
//	}
//
//	models.List = lists
//	models.Page = req.Page
//	models.PerPage = req.PerPage
//	models.PageCount = (count + req.PerPage - 1) / req.PerPage
//
//	return serializer.Suc(models)
//}

//func (s *sUser) Edit(ctx *gin.Context, req forms.AdminUserEditReq) serializer.Response {
//	q := query.Use(config.AdminDB).AdminUser
//
//	logrus.Warnf("sUser Edit req:%+v", req)
//
//	if req.RoleID <= 0 {
//		return serializer.ParamErr("角色不能为空", nil)
//	}
//
//	if req.UserName == "" {
//		return serializer.ParamErr("用户名不能为空", nil)
//	}
//
//	// 修改
//	if req.ID > 0 {
//		update := &model.AdminUser{
//			UserName:  req.UserName,
//			RoleID:    int32(req.RoleID),
//			Nickname:  req.Nickname,
//			Status:    req.Status,
//			UpdatedAt: time.Now(),
//		}
//		_, err := q.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(update)
//		if err != nil {
//			return serializer.Err(consts.CodeParamErr, "更新出错", err)
//		}
//		// 维护redis token
//		config.TokenRedis.Del(config.GetUserTokenKey(req.ID))
//		return serializer.Suc(nil)
//	}
//
//	if req.Password == "" {
//		return serializer.ParamErr("密码不能为空", nil)
//	}
//
//	// 加密密码
//	password, err := s.SetPassword(req.Password)
//	if err != nil {
//		return serializer.Err(
//			consts.CodeEncryptError,
//			"密码加密失败",
//			err,
//		)
//	}
//
//	// 新增
//	create := &model.AdminUser{
//		UserName:       req.UserName,
//		RoleID:         int32(req.RoleID),
//		Nickname:       req.Nickname,
//		PasswordDigest: password,
//		Status:         req.Status,
//		UpdatedAt:      time.Now(),
//		CreatedAt:      time.Now(),
//	}
//
//	if err = query.Use(config.AdminDB).AdminUser.WithContext(ctx).Create(create); err != nil {
//		return serializer.DBErr(err.Error(), err)
//	}
//
//	return serializer.Suc(nil)
//}

//func (s *sUser) ResetPassword(ctx *gin.Context, req forms.AdminUserResetPasswordReq) serializer.Response {
//	q := query.Use(config.AdminDB).AdminUser
//
//	logrus.Warnf("sUser ResetPassword req:%+v", req)
//
//	if req.ID <= 0 {
//		return serializer.ParamErr("用于ID不能为空", nil)
//	}
//
//	if req.Password == "" {
//		return serializer.ParamErr("密码不能为空", nil)
//	}
//
//	// 加密密码
//	password, err := s.SetPassword(req.Password)
//	if err != nil {
//		return serializer.Err(
//			consts.CodeEncryptError,
//			"密码加密失败",
//			err,
//		)
//	}
//	update := &model.AdminUser{
//		PasswordDigest: password,
//		UpdatedAt:      time.Now(),
//	}
//
//	_, err = q.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(update)
//	if err != nil {
//		return serializer.Err(consts.CodeParamErr, "更新出错", err)
//	}
//	// 维护redis token
//	config.TokenRedis.Del(config.GetUserTokenKey(req.ID))
//	return serializer.Suc(nil)
//}

//func (s *sUser) UpdatePassword(ctx *gin.Context, req forms.AdminUserUpdatePasswordReq) serializer.Response {
//	q := query.Use(config.AdminDB).AdminUser
//
//	logrus.Warnf("sUser UpdatePassword req:%+v", req)
//
//	userId := token.GetUID(ctx)
//	if userId <= 0 {
//		return serializer.ParamErr("用户信息获取失败", nil)
//	}
//
//	models, err := q.WithContext(ctx).Where(q.ID.Eq(userId)).First()
//	if err != nil {
//		return serializer.ParamErr(err.Error(), err)
//	}
//
//	if models == nil {
//		return serializer.ParamErr("用户不存在", nil)
//	}
//
//	if !s.CheckPasswordRight(models.PasswordDigest, req.OldPassword) {
//		return serializer.ParamErr("老密码不正确", nil)
//	}
//
//	// 加密密码
//	password, err := s.SetPassword(req.NewPassword)
//	if err != nil {
//		return serializer.Err(
//			consts.CodeEncryptError,
//			"密码加密失败",
//			err,
//		)
//	}
//	update := &model.AdminUser{
//		PasswordDigest: password,
//		UpdatedAt:      time.Now(),
//	}
//
//	_, err = q.WithContext(ctx).Where(q.ID.Eq(userId)).Updates(update)
//	if err != nil {
//		return serializer.Err(consts.CodeParamErr, "更新出错", err)
//	}
//
//	// 修改token状态
//	config.TokenRedis.Del(config.GetUserTokenKey(userId))
//
//	return serializer.Suc(nil)
//}

//func (s *sUser) GetUserInfo(c *gin.Context) (*model.AdminUser, error) {
//	q := query.Use(config.AdminDB).AdminUser
//
//	userId := token.GetUID(c)
//	if userId <= 0 {
//		c.JSON(200, serializer.Err(consts.CodeNoPermission, "用户信息获取失败", nil))
//		c.Abort()
//	}
//
//	return q.WithContext(c).Where(q.ID.Eq(userId)).First()
//}

//func (s *sUser) GetUserRoleId(c *gin.Context) int64 {
//	info, err := s.GetUserInfo(c)
//	if err != nil {
//		return 0
//	}
//
//	if info == nil {
//		return 0
//	}
//
//	return int64(info.RoleID)
//}

//func (s *sUser) GetUserByUnionID(unionID string) (*model.AdminUser, error) {
//	q := query.Use(config.AdminDB).AdminUser
//	return q.Where(q.FeishuUnionID.Eq(unionID)).First()
//}
