package backend

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

func GetChain(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
	}

	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
	}

	chainService := chain_service.Chain{ID: id}
	exists, err := chainService.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrChainNotFound, nil)
		return
	}

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

	chain, err := chainService.Get()
	if err != nil {
		handler.SendResponse(c, errno.ErrChainNotFound, nil)
		return
	}

	handler.SendResponse(c, nil, chain)
}

func GetChains(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
	}

	valid := validation.Validation{}

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

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

	chainService := chain_service.Chain{
		Platform: platform,
		PageNum:  util.GetPage(c),
		PageSize: util.GetLimit(c),
	}

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

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

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

	handler.SendResponse(c, nil, data)
}

func GetUserChains(c *gin.Context) {
	token := c.Request.Header.Get("Token")
	user, _ := util.ParseToken(token)
	group := user.UserInfo.Group
	userChainService := chain_service.Chain{}
	if ("administrator" != group) {
		walletService := wallet_service.Wallet{Id: user.UserInfo.PlatformId}
		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()
		userChainService = chain_service.Chain{
			ID: wallet.ChainId,
		}
	}

	platform_chain, err := userChainService.GetUserChain()
	if err != nil {
		handler.SendResponse(c, errno.InternalServerError, nil)
		return
	}

	data := make(map[string]interface{})

	data["items"] = platform_chain
	data["total"] = len(platform_chain)

	handler.SendResponse(c, nil, data)
}

func AddChain(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
	}

	chain := validate_service.Chain{}
	c.ShouldBindJSON(&chain)

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

	chainService := chain_service.Chain{
		Platform:   chain.Platform,
		Address:    chain.Address,
		PrivateKey: chain.PrivateKey,
		Exer:       chain.Exer,
		Token:      chain.Token,
		Fee:        chain.Fee,
		BrowerUrl:  chain.BrowerUrl,
		Icon:       chain.Icon,
		Lock:       chain.Lock,
	}

	count, err := chainService.Count()
	if err != nil || count > 0 {
		handler.SendResponse(c, errno.ErrExistChain, nil)
		return
	}

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

	handler.SendResponse(c, nil, nil)
}

func EditChain(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
	}

	chain := validate_service.EditChain{}
	c.ShouldBindJSON(&chain)

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

	chainService := chain_service.Chain{
		ID:         chain.Id,
		Platform:   chain.Platform,
		Address:    chain.Address,
		PrivateKey: chain.PrivateKey,
		Exer:       chain.Exer,
		Token:      chain.Token,
		Fee:        chain.Fee,
		BrowerUrl:  chain.BrowerUrl,
		Icon:       chain.Icon,
		Lock:       chain.Lock,
	}

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

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

	handler.SendResponse(c, nil, nil)
}

func DeleteChain(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
	}

	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
	}

	chainService := chain_service.Chain{ID: id}
	exists, err := chainService.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

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

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

	handler.SendResponse(c, nil, nil)
}
