package backend

import (
	"bwallet/pkg/errno"
	"bwallet/pkg/handler"
	"bwallet/pkg/util"
	"bwallet/service/wallet_service"
	"bwallet/validate_service"
	"github.com/Unknwon/com"
	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
	"strings"
)

func GetWallet(c *gin.Context) {
	id := com.StrTo(c.DefaultQuery("id", "0")).MustInt()
	valid := validation.Validation{}
	valid.Min(id, 1, "id").Message("ID必须大于0")
	if valid.HasErrors() {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)
	group := user.UserInfo.Group
	var platform_id int
	platform_id = id
	if ("administrator" != group && id != user.UserInfo.PlatformId) {
		handler.SendResponse(c, errno.ErrUserTokenIncorrect, nil)
		return
	}

	walletService := wallet_service.Wallet{Id: platform_id}
	exists, err := walletService.ExistById()

	if err != nil {
		handler.SendResponse(c, errno.ErrWalletNotFound, nil)
		return
	}

	if (!exists) {
		handler.SendResponse(c, errno.ErrWalletNotFound, nil)
		return
	}

	wallet, err := walletService.Get()
	if err != nil {
		handler.SendResponse(c, errno.ErrWalletNotFound, nil)
		return
	}

	handler.SendResponse(c, nil, wallet)
}

func GetWallets(c *gin.Context) {
	valid := validation.Validation{}

	name := ""
	if arg := c.Query("name"); arg != "" {
		name = c.Query("name")
	}

	if valid.HasErrors() {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)

	var platform_id int
	platform_id = user.UserInfo.PlatformId
	group := user.UserInfo.Group

	walletService := wallet_service.Wallet{}
	if ("administrator" == group) {
		walletService = wallet_service.Wallet{
			Name:     name,
			PageNum:  util.GetPage(c),
			PageSize: util.GetLimit(c),
		}
	} else {
		walletService = wallet_service.Wallet{
			Id:       platform_id,
			Name:     name,
			PageNum:  util.GetPage(c),
			PageSize: util.GetLimit(c),
		}
	}

	total, err := walletService.Count()
	if err != nil {
		handler.SendResponse(c, errno.ErrCountWallet, nil)
		return
	}

	wallets, err := walletService.GetAll()
	if err != nil {
		handler.SendResponse(c, errno.InternalServerError, nil)
		return
	}

	data := make(map[string]interface{})
	data["items"] = wallets
	data["total"] = total

	handler.SendResponse(c, nil, data)
}

func AddWallet(c *gin.Context) {
	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)
	group := user.UserInfo.Group
	if ("administrator" != group) {
		handler.SendResponse(c, errno.ErrUserAuthIncorrect, nil)
		return
	}

	wallet := validate_service.Wallet{}
	c.ShouldBindJSON(&wallet)

	//方法一
	if ok, errors := validate_service.ValidateInputs(wallet); !ok {
		for _, err := range errors {
			handler.SendResponse(c, errno.ErrBind, strings.Join(err, " "))
			return
		}
	}
	//方法二
	/*
		validate := validator.New()
		err := validate.Struct(wallet)

		if err != nil {
			if _, ok := err.(*validator.InvalidValidationError); ok {
				fmt.Println("err is ", err)
				return
			}
			errors := make(map[string][]string)
			reflected := reflect.ValueOf(wallet)
			for _, err := range err.(validator.ValidationErrors) {
				field, _ := reflected.Type().FieldByName(err.StructField())
				var name string
				if name = field.Tag.Get("json"); name == "" {
					name = strings.ToLower(err.StructField())
				}
				//if err.Field() == "DownloadUrl" {
				switch err.Tag() {
				case "required":
					errors[name] = append(errors[name], "The "+err.Field()+" is required")
					break
				case "email":
					errors[name] = append(errors[name], "The "+err.Field()+" should be a valid email")
					break
				case "url":
					errors[name] = append(errors[name], "The "+err.Field()+" should be a valid url")
					break
				default:
					errors[name] = append(errors[name], "The "+err.Field()+" is invalid")
					break
				}

				fmt.Println(err.Namespace())
				fmt.Println(err.Field())
				fmt.Println(err.StructNamespace()) // can differ when a custom TagNameFunc is registered or
				fmt.Println(err.StructField())     // by passing alt name to ReportError like below
				fmt.Println(err.Tag())
				fmt.Println(err.ActualTag())
				fmt.Println(err.Kind())
				fmt.Println(err.Type())
				fmt.Println(err.Value())
				fmt.Println(err.Param())
			}

			fmt.Println(errors)
			return
		}
	*/

	walletService := wallet_service.Wallet{
		Name:        wallet.Name,
		DownloadUrl: wallet.DownloadUrl,
		Introduce:   wallet.Introduce,
		Summary:     wallet.Summary,
		ChainId:     wallet.ChainId,
		IssueCharge: wallet.IssueCharge,
		ChargeUnit:  wallet.ChargeUnit,
	}

	if err := walletService.Add(); err != nil {
		handler.SendResponse(c, errno.ErrAddWallet, nil)
		return
	}

	handler.SendResponse(c, nil, nil)
}

func EditWallet(c *gin.Context) {
	wallet := validate_service.EditWallet{}
	c.ShouldBindJSON(&wallet)

	//方法一
	if ok, errors := validate_service.ValidateInputs(wallet); !ok {
		for _, err := range errors {
			handler.SendResponse(c, errno.ErrBind, strings.Join(err, " "))
			return
		}
	}

	walletService := wallet_service.Wallet{
		Id:          wallet.Id,
		Name:        wallet.Name,
		DownloadUrl: wallet.DownloadUrl,
		Introduce:   wallet.Introduce,
		Summary:     wallet.Summary,
		//ChainId:     wallet.ChainId,
		//IssueCharge: wallet.IssueCharge,
		//ChargeUnit:  wallet.ChargeUnit,
	}

	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)
	group := user.UserInfo.Group
	if ("administrator" != group && user.UserInfo.PlatformId != wallet.Id) {
		handler.SendResponse(c, errno.ErrUserAuthIncorrect, nil)
		return
	}

	exists, err := walletService.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrWalletNotFound, nil)
		return
	}
	if !exists {
		handler.SendResponse(c, errno.ErrWalletNotFound, nil)
		return
	}

	if err := walletService.Edit(); err != nil {
		handler.SendResponse(c, errno.ErrUpdateWallet, nil)
		return
	}

	handler.SendResponse(c, nil, nil)
}

func DeleteWallet(c *gin.Context) {
	id := com.StrTo(c.DefaultQuery("id", "0")).MustInt()
	valid := validation.Validation{}
	valid.Min(id, 1, "id").Message("ID必须大于0")
	if valid.HasErrors() {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)
	group := user.UserInfo.Group
	if ("administrator" != group && user.UserInfo.PlatformId != id) {
		handler.SendResponse(c, errno.ErrUserAuthIncorrect, nil)
		return
	}

	walletService := wallet_service.Wallet{Id: id}
	exists, err := walletService.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	if !exists {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	err = walletService.Delete()
	if err != nil {
		handler.SendResponse(c, errno.ErrDeleteWallet, nil)
		return
	}

	handler.SendResponse(c, nil, nil)
}
