package v1

import (
	"bwallet/pkg/errno"
	"bwallet/pkg/handler"
	"bwallet/pkg/util"
	"bwallet/service/auth_service"
	"bwallet/service/coin_service"
	"bwallet/service/platform_chain_service"
	"bwallet/service/recommend_coin_service"
	"bwallet/validate_service"
	"github.com/Unknwon/com"
	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
	"strconv"
	"strings"
)

func GetCoin(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")
	authService := auth_service.Auth{Token: token}
	auth, _ := authService.GetUserInfo()
	group := auth.Group
	var platform_id int
	if ("administrator" == group) {
		platform_id = com.StrTo(c.DefaultQuery("platform_id", "1")).MustInt()
	} else {
		platform_id = auth.PlatformId
	}
	coinService := coin_service.Coin{
		Id:         id,
		PlatformId: strconv.Itoa(platform_id),
		PageNum:    util.GetPage(c),
		PageSize:   util.GetLimit(c),
	}

	coin, err := coinService.GetAll()
	if err != nil {
		handler.SendResponse(c, errno.ErrCoinNotFound, nil)
		return
	}

	handler.SendResponse(c, nil, coin)
	return
}

func GetUserChains(c *gin.Context) {
	data := make(map[string]interface{})
	token := c.Request.Header.Get("Token")
	authService := auth_service.Auth{Token: token}
	auth, _ := authService.GetUserInfo()
	group := auth.Group

	coinService := coin_service.Coin{}
	if ("administrator" != group) {
		platformChainService := platform_chain_service.PlatformChain{
			PlatformId: auth.PlatformId,
			IsPrimary:  1,
		}
		platform_chain, err := platformChainService.GetAll()
		if err != nil {
			handler.SendResponse(c, errno.InternalServerError, nil)
			return
		}
		var platform string
		for _, val := range platform_chain {
			if nil != val.ChainInfo {
				platform = val.ChainInfo.Platform
			}
		}
		if "" == platform {
			data["items"] = nil
			data["total"] = 0
			handler.SendResponse(c, nil, data)
			return
		}
		coinService.Platform = platform
	}

	platforms, err := coinService.GetAllPlatform()
	if err != nil {
		handler.SendResponse(c, errno.InternalServerError, nil)
		return
	}

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

	handler.SendResponse(c, nil, data)
}

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

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

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

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

	//platform_id := ""
	//if arg := c.Query("platform_id"); arg != "" {
	//	platform_id = c.DefaultQuery("platform_id", "1")
	//}

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

	coinService := coin_service.Coin{
		Name:     name,
		Chain:    chain,
		Platform: platform,
		//PlatformId: platform_id,
		PageNum:  util.GetPage(c),
		PageSize: util.GetLimit(c),
	}

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

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

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

	handler.SendResponse(c, nil, data)
}

func AddCoin(c *gin.Context) {
	token := c.Request.Header.Get("Token")
	authService := auth_service.Auth{Token: token}
	auth, _ := authService.GetUserInfo()
	group := auth.Group

	if ("administrator" != group) {
		handler.SendResponse(c, errno.ErrUserAuthIncorrect, nil)
		return
	}

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

	coinService := coin_service.Coin{
		Name:           coin.Name,
		Nickname:       coin.Nickname,
		Icon:           coin.Icon,
		Introduce:      coin.Introduce,
		Official:       coin.Official,
		Paper:          coin.Paper,
		Platform:       coin.Platform,
		Chain:          coin.Chain,
		Release:        coin.Release,
		AreaSearch:     coin.AreaSearch,
		PublishCount:   coin.PublishCount,
		CirculateCount: coin.CirculateCount,
		Decimals:       coin.Decimals,
		Address:        coin.Address,
		Treaty:         coin.Treaty,
		PlatformId:     "1",
	}

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

func EditCoin(c *gin.Context) {
	coin := validate_service.EditCoin{}
	c.ShouldBindJSON(&coin)

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

	token := c.Request.Header.Get("Token")
	authService := auth_service.Auth{Token: token}
	auth, _ := authService.GetUserInfo()
	group := auth.Group

	coin_model := coin_service.Coin{Id: coin.Id}
	exists, err := coin_model.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrCoinNotFound, nil)
		return
	}
	if !exists {
		handler.SendResponse(c, errno.ErrCoinNotFound, nil)
		return
	}

	coin_exist, _ := coin_model.Get()

	platformChainService := platform_chain_service.PlatformChain{
		PlatformId: auth.PlatformId,
		IsPrimary:  1,
	}
	platform_chain, err := platformChainService.GetAll()
	if err != nil {
		handler.SendResponse(c, errno.InternalServerError, nil)
		return
	}

	var platform string
	for _, val := range platform_chain {
		if nil != val.ChainInfo {
			platform = val.ChainInfo.Platform
		}
	}

	if ("administrator" != group) {
		if (strings.ToUpper(coin_exist.Platform) != strings.ToUpper(platform)) {
			handler.SendResponse(c, errno.ErrAuthCoin, nil)
			return
		}
	}

	coinService := coin_service.Coin{
		Id:             coin.Id,
		Name:           coin.Name,
		Nickname:       coin.Nickname,
		Icon:           coin.Icon,
		Introduce:      coin.Introduce,
		Official:       coin.Official,
		Paper:          coin.Paper,
		Platform:       coin.Platform,
		Chain:          coin.Chain,
		Release:        coin.Release,
		AreaSearch:     coin.AreaSearch,
		PublishCount:   coin.PublishCount,
		CirculateCount: coin.CirculateCount,
		Decimals:       coin.Decimals,
		Address:        coin.Address,
		PlatformId:     coin_exist.PlatformId,
		Treaty:         coin.Treaty,
	}

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

	handler.SendResponse(c, nil, nil)
}

func DeleteCoin(c *gin.Context) {
	token := c.Request.Header.Get("Token")
	authService := auth_service.Auth{Token: token}
	auth, _ := authService.GetUserInfo()
	group := auth.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
	}

	coinService := coin_service.Coin{Id: id}
	exists, err := coinService.ExistById()
	if err != nil {
		handler.SendResponse(c, errno.ErrValidation, nil)
		return
	}

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

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

	recommendCoinService := recommend_coin_service.RecommendCoin{Cid: id}
	recommendCoinService.DeleteByCondition()

	handler.SendResponse(c, nil, nil)
}

/*
func GetCoinsPlatform(c *gin.Context) {
	appG := app.Gin{c}
	coinService := coin_service.Coin{}
	coins, err := coinService.GetCoinsPlatform()
	if err != nil {
		appG.Response(http.StatusInternalServerError, e.ERROR_GET_COIN_FAIL, nil)
		return
	}

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

	appG.Response(http.StatusOK, e.SUCCESS, data)
}
*/

func GetPrimaryChains(c *gin.Context) {
	data := make(map[string]interface{})
	data["items"] = [] string{"BTC", "ETH", "BTY", "DCR"}

	handler.SendResponse(c, nil, data)
}

func GetTypes(c *gin.Context) {
	data := make(map[string]interface{})
	data["items"] = [] string{"coins", "er c20/token"}

	handler.SendResponse(c, nil, data)
}
