package controllers

import (
	"ai_developer_admin/libs/jose"
	"ai_developer_admin/libs/kong"
	"ai_developer_admin/libs/mysql"
	"ai_developer_admin/libs/odysseus"
	"ai_developer_admin/libs/redis"
	"ai_developer_admin/libs/utils"
	"ai_developer_admin/models"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"errors"
	"github.com/beego/beego/v2/core/logs"
	beego "github.com/beego/beego/v2/server/web"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type UserController struct {
	MainController
}

//func (u *UserController) respond(code int, message string, data ...interface{}) {
//	u.Ctx.Output.SetStatus(code)
//	var d interface{}
//	if len(data) > 0 {
//		d = data[0]
//	}
//	u.Data["json"] = struct {
//		Code    int         `json:"code"`
//		Message string      `json:"message"`
//		Data    interface{} `json:"data,omitempty"`
//	}{
//		Code:    code,
//		Message: message,
//		Data:    d,
//	}
//	u.ServeJSON()
//}

//func (u *UserController) Test() {
//	info, err := u.Check()
//	if err != nil {
//		u.respond(http.StatusUnauthorized, err.Error())
//		return
//	}
//	u.respond(http.StatusOK, "", info)
//}

func (server *UserController) Login() {
	var err error
	body := server.Ctx.Input.RequestBody
	loginRequest := models.LoginRequest{}
	err = json.Unmarshal(body, &loginRequest) //解析body中数据
	logs.Debug("loginRequest", loginRequest)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}
	//if len(user.Username) == 0 {
	//	u.respond(http.StatusBadRequest, "用户名不能为空")
	//	return
	//}

	claims, err := jose.Verify("https://api-auth.web3auth.io/jwks", loginRequest.Web3AuthPublicKey, loginRequest.IdToken)
	if err != nil {
		server.respond(models.LoginFailed, "Web3Auth 验证失败")
		return
	}

	if claims.Exp <= time.Now().Unix() {
		server.respond(models.LoginFailed, "Web3Auth 登录已超时")
		return
	}

	clientId, _ := beego.AppConfig.String("web3ClientId")

	if strings.Compare(clientId, claims.Aud) != 0 {
		server.respond(models.LoginFailed, "web3auth clientId 错误")
		return
	}

	user := loginRequest.RequstUser
	//if len(user.VerifierId) == 0 {
	user.VerifierId = claims.VerifierId
	//}
	if len(user.Username) == 0 {
		user.Username = "ai_" + generatorMD5(user.Mail)[0:8]
	}
	if len(user.ProfileImage) == 0 {
		user.ProfileImage = claims.ProfileImage
	}

	checkUser := &models.User{Mail: user.Mail}
	err = mysql.GetMysqlInstace().Ormer.Read(checkUser, "mail")
	stats := mysql.Ping()
	if stats != nil {
		server.respond(models.CreateUserFailed, stats.Error())
		return
	}
	if err != nil && stats == nil {
		checkUser, err = regisgerUser(user)
		if checkUser == nil {
			server.respond(models.CreateUserFailed, err.Error())
			return
		}
	}
	duration := claims.Exp - claims.Iat
	tokenString, err := utils.GenerateToken(checkUser, checkUser.Id, int(duration))
	if err != nil {
		server.respond(models.LoginFailed, "登录失败")
		return
	}
	//checkUserLevel := &models.UserLevel{Id: checkUser.LevelId}
	//err = mysql.GetMysqlInstace().Ormer.Read(checkUserLevel)
	//if err != nil {
	//	logs.Debug("Recharge 用户等级查找失败")
	//} else {
	//	odysseus.SyncCredit(strconv.Itoa(checkUser.Id), checkUserLevel.FreeQuota)
	//}

	key := "token:user-" + strconv.Itoa(checkUser.Id)
	//u.SetSession(key, tokenString)
	//lifetime, _ := beego.AppConfig.Int64("sessiongcmaxlifetime")
	redis.SetKeyAndData(key, tokenString, time.Duration(duration)*time.Second)
	server.Ctx.Output.Header("Authorization", tokenString) // set token into header
	//session := u.GetSession(key)
	//logs.Debug("login session", session)

	server.respond(http.StatusOK, "")
}

func (server *UserController) Logout() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	key := "token:user-" + strconv.Itoa(info.UserID)
	redis.DeleteKey(key)
	server.respond(http.StatusUnauthorized, "")
}

func (server *UserController) Regisger() {
	var err error
	user := models.User{}
	body := server.Ctx.Input.RequestBody
	err = json.Unmarshal(body, &user) //解析body中数据
	logs.Debug("user", user)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}
	if len(user.Username) == 0 {
		server.respond(models.MissingParameter, "用户名不能为空")
		return
	}

	_, err = regisgerUser(user)
	if err != nil {
		server.respond(models.CreateUserFailed, err.Error())
		return
	}

	server.respond(http.StatusOK, "")
}

func (server *UserController) UserInfo() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	checkUser := &models.User{Id: info.UserID}
	err = mysql.GetMysqlInstace().Ormer.Read(checkUser)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	balance, err := odysseus.GetUserBalance(int64(checkUser.Id))
	if err == nil {
		checkUser.Balance = balance
	}
	server.respond(http.StatusOK, "", checkUser)
}

func regisgerUser(user models.User) (*models.User, error) {
	var err error
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("user")
	usernameQs := qs.Filter("mail", user.Mail)
	var count int64
	count, err = usernameQs.Count()
	if count > 0 {
		return nil, errors.New("用户已存在")
	}
	//if len(user.CustomId) > 0 {
	//	customIdQs := qs.Filter("custom_id", user.CustomId)
	//	count, err = customIdQs.Count()
	//	if count > 0 {
	//		return nil, errors.New("您指定的客户id已存在")
	//	}
	//}

	user.CreatedTime = time.Now()
	user.UpdatedTime = user.CreatedTime
	user.Level = 0
	user.Role = 4

	_, err = mysql.GetMysqlInstace().Ormer.Insert(&user)
	if err != nil {
		return nil, errors.New("注册用户失败")
	}

	checkUser := &models.User{Username: user.Username}
	err = mysql.GetMysqlInstace().Ormer.Read(checkUser, "username")
	if err != nil {
		return nil, errors.New("注册用户失败")
	}
	checkUser.CustomId = strconv.Itoa(checkUser.Id)

	data, err := kong.CreateUser(checkUser)
	if err != nil {
		mysql.GetMysqlInstace().Ormer.Delete(checkUser)
		return nil, err
	}
	if data.Id == "" {
		mysql.GetMysqlInstace().Ormer.Delete(checkUser)
		return nil, errors.New(data.Message)
	}

	checkUserLevel := &models.UserLevel{Level: checkUser.Level}
	err = mysql.GetMysqlInstace().Ormer.Read(checkUserLevel, "level")
	if err != nil {
		logs.Debug("Recharge 用户等级查找失败")
	} else {
		plugin, err := kong.SetRateLimit(checkUser, checkUserLevel, "")
		if err == nil {
			checkUser.RateLimitPluginId = plugin.Id
		}
	}

	mysql.GetMysqlInstace().Ormer.Update(checkUser)

	return checkUser, nil
}

func generatorMD5(code string) string {
	MD5 := md5.New()
	_, _ = io.WriteString(MD5, code)
	return hex.EncodeToString(MD5.Sum(nil))
}
