package req

import (
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/mysql"
	"github.com/gin-gonic/gin"
	"hilo-group/domain/cache/user_c"
	"hilo-group/domain/model/res_m"
	"hilo-group/myerr"
	"hilo-group/myerr/bizerr"
	"strconv"
	"strings"
)

func GetUserId(c *gin.Context) (mysql.ID, error) {
	if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
		userId := userIdStr.(uint64)
		return userId, nil
	}
	return 0, bizerr.ParaMissing
}

// 获取userId和externalId
func GetUserIdAndExtId(c *gin.Context, myContext *mycontext.MyContext) (mysql.ID, string, error) {
	if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
		userId := userIdStr.(uint64)

		externalId, ok := c.Get(mycontext.EXTERNAL_ID)
		if ok {
			return userId, externalId.(string), nil
		} else {
			user, err := user_c.GetUserTinyById(domain.CreateModelContext(myContext), userId)
			if err != nil {
				return 0, "", bizerr.ExternalIdNoExist
			}
			return userId, user.ExternalId, nil
		}
	}
	return 0, "", bizerr.ParaMissing
}

// 获取userId和ExtId和code
func GetUserIdExtIdCode(c *gin.Context, myContext *mycontext.MyContext) (mysql.ID, string, string, error) {
	if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
		userId := userIdStr.(uint64)

		userCode, ok1 := c.Get(mycontext.CODE)
		externalId, ok2 := c.Get(mycontext.EXTERNAL_ID)
		if ok1 && ok2 {
			return userId, externalId.(string), userCode.(string), nil
		} else {
			user, err := user_c.GetUserTinyById(domain.CreateModelContext(myContext), userId)
			if err != nil {
				return 0, "", "", bizerr.ExternalIdNoExist
			}
			return userId, user.ExternalId, user.Code, nil
		}
	}
	return 0, "", "", bizerr.ParaMissing
}

// 获取userId和LANGUAGE
func GetUserIdLang(c *gin.Context, myContext *mycontext.MyContext) (mysql.ID, string, error) {
	if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
		userId := userIdStr.(uint64)

		lang, ok := c.Get(mycontext.LANGUAGE)
		if ok {
			return userId, lang.(string), nil
		} else {
			model := domain.CreateModelContext(myContext)
			user, err := user_c.GetUserTinyById(model, userId)
			if err != nil {
				return 0, "", bizerr.ExternalIdNoExist
			}
			lang, err := res_m.GetLangeByCountry(model.Db, user.Country)
			if err != nil {
				return 0, "", err
			}
			return userId, lang, nil
		}
	}
	return 0, "", bizerr.ParaMissing
}

// 同时获取userId和externalId, nick, avatar, country
func GetUserEx(c *gin.Context, myContext *mycontext.MyContext) (mysql.ID, string, string, string, string, error) {
	if userIdStr, ok := c.Keys[mycontext.USERID]; ok {
		userId := userIdStr.(uint64)

		externalId, ok1 := c.Get(mycontext.EXTERNAL_ID)
		nick, ok2 := c.Get(mycontext.NICK)
		avatar, ok3 := c.Get(mycontext.AVATAR)
		country, ok4 := c.Get(mycontext.COUNTRY)
		ok := ok1 && ok2 && ok3 && ok4
		if ok {
			return userId, externalId.(string), nick.(string), avatar.(string), country.(string), nil
		} else {
			//var user user_m.User
			//if err := mysql.Db.First(&user, userId).Error; err != nil {
			//	return 0, "", "", "", "", bizerr.ExternalIdNoExist
			//}
			user, err := user_c.GetUserTinyById(domain.CreateModelContext(myContext), userId)
			if err != nil {
				return 0, "", "", "", "", bizerr.ExternalIdNoExist
			}
			return userId, user.ExternalId, user.Nick, user.Avatar, user.Country, nil
		}
	}
	return 0, "", "", "", "", bizerr.ParaMissing
}

func GetAppImei(c *gin.Context) (string, error) {
	imei := c.GetHeader(mycontext.IMEI)
	if len(imei) <= 0 {
		return "", myerr.WrapErr(bizerr.ParaMissing)
	}
	return imei, nil
}

func GetRequestIP(c *gin.Context) string {
	reqIP := c.ClientIP()
	if reqIP == "::1" {
		reqIP = "127.0.0.1"
	}
	return reqIP
}

func GetAppVersion(c *gin.Context) (string, int, int, int, error) {
	deviceType := c.GetHeader(mycontext.DEVICETYPE)
	if len(deviceType) <= 0 {
		return "", 0, 0, 0, bizerr.ParaMissing
	}
	appVerStr := c.GetHeader(mycontext.APP_VERSION)
	if len(appVerStr) <= 0 {
		return "", 0, 0, 0, bizerr.ParaMissing
	}
	s := strings.Split(appVerStr, ".")
	if len(s) < 3 {
		return "", 0, 0, 0, bizerr.InvalidParameter
	}
	major, err := strconv.Atoi(s[0])
	if err != nil || major < 0 {
		return "", 0, 0, 0, bizerr.InvalidParameter
	}
	minor, err := strconv.Atoi(s[1])
	if err != nil || minor < 0 {
		return "", 0, 0, 0, bizerr.InvalidParameter
	}
	min, err := strconv.Atoi(s[2])
	if err != nil || min < 0 {
		return "", 0, 0, 0, bizerr.InvalidParameter
	}
	return deviceType, major, minor, min, nil
}