package password

import (
	"crypto/sha1"
	"errors"
	"fmt"

	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/auth2"
	"git.rosy.net.cn/jx-callback/business/auth2/authprovider"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
)

const (
	AuthType = auth2.AuthTypePassword
)

type Auther struct {
	authprovider.DefAuther
}

var (
	AutherObj *Auther
)

var (
	ErrUserAndPassNotMatch = errors.New("用户名密码不匹配")
)

func init() {
	AutherObj = new(Auther)
	auth2.RegisterAuther(AuthType, AutherObj)
}

func (a *Auther) VerifySecret(userID, passMD5 string) (authBindEx *auth2.AuthBindEx, err error) {
	var authBind *model.AuthBind
	if authBind, err = dao.GetAuthBind(dao.GetDB(), model.AuthBindTypeAuth, AuthType, userID); err == nil {
		if err = a.checkPassword(authBind, passMD5); err == nil {
			authBindEx = &auth2.AuthBindEx{
				AuthBind: *authBind,
			}
		}
	} else if dao.IsNoRowsError(err) {
		err = auth2.ErrUserAuthTypeNotExist
	}
	return authBindEx, err
}

// 特殊接口
func (a *Auther) ChangePassword(userID, userName, oldPassMD5, newPassMD5 string) (err error) {
	var authBind *model.AuthBind
	db := dao.GetDB()
	salt := utils.GetUUID()
	encryptPwd := a.encryptPassword(newPassMD5, salt)
	if authBind, err = dao.GetAuthBind(db, model.AuthBindTypeAuth, AuthType, userID); err == nil {
		if err = a.checkPassword(authBind, oldPassMD5); err == nil || authBind.AuthSecret == "" { // 如果原密码为空，不判断原密码，代表重置密码
			_, err = dao.UpdateEntityLogically(db, authBind, map[string]interface{}{
				"AuthSecret":  encryptPwd,
				"AuthSecret2": salt,
			}, userName, nil)
		}
	} else if dao.IsNoRowsError(err) {
		err = a.AddAuthBind(&auth2.AuthBindEx{
			AuthBind: model.AuthBind{
				UserID:      userID,
				Type:        AuthType,
				AuthID:      userID,
				AuthSecret:  encryptPwd,
				AuthSecret2: salt,
			},
		}, userName)
	}
	return err
}

func (a *Auther) encryptPassword(password, salt string) string {
	return fmt.Sprintf("%x", sha1.Sum([]byte(password+salt)))
}

func (a *Auther) checkPassword(authBind *model.AuthBind, passMD5 string) (err error) {
	if authBind.AuthSecret != a.encryptPassword(passMD5, authBind.AuthSecret2) {
		return ErrUserAndPassNotMatch
	}
	return nil
}
