package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt"
)

func Auth() gin.HandlerFunc {
	return func(c *gin.Context) {
		bearer := c.Request.Header.Get("Authorization")
		if bearer == "" || !strings.HasPrefix(bearer, "Bearer ") {
			resBizJSON(c, genErrBody(ResUnauthorized))
			c.Abort()
			return
		}
		tokenString := bearer[7:]
		token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) {
			return hmacSampleSecret, nil
		})
		if err != nil {
			resBizJSON(c, genErrBody(ResUnauthorized))
			c.Abort()
			return
		}
		if claims, ok := token.Claims.(*TokenClaims); ok && token.Valid {
			if time.Now().Unix() < claims.UatExp {
				c.Set("jwtClaim", claims)
				c.Set("jwtClaimUat", claims.Uat)
				c.Set("jwtToken", tokenString)
				c.Next()
			} else if time.Now().Unix() < claims.RtExp {
				tat, err := fetchTenantToken(c, claims.AppId)
				if err != nil {
					resBizJSON(c, genCusErrBody(ResInternalErr, err.Error()))
					c.Abort()
					return
				}
				rpostBody, _ := json.Marshal(map[string]string{
					"grant_type":    "refresh_token",
					"refresh_token": claims.Rt,
				})
				rresp, err := refreshUserToken(bytes.NewBuffer(rpostBody), tat)
				if err != nil {
					resBizJSON(c, genErrBody(ResUnauthorized))
					c.Abort()
					return
				}
				defer rresp.Body.Close()
				rbody, _ := ioutil.ReadAll(rresp.Body)
				var jsonRB RefreshUserAccessTokenInfoResp
				if err := json.Unmarshal(convertJSON2Camel(rbody), &jsonRB); err != nil {
					resBizJSON(c, genCusErrBody(ResInternalErr, err.Error()))
					c.Abort()
					return
				}
				if jsonRB.Code != 0 {
					resBizJSON(c, genErrBody(ResUnauthorized))
					c.Abort()
					return
				}
				jd := jsonRB.Data
				rd := UserInfoData{
					Name:         jd.Name,
					EnName:       jd.EnName,
					AvatarUrl:    jd.AvatarUrl,
					AvatarThumb:  jd.AvatarThumb,
					AvatarMiddle: jd.AvatarMiddle,
					AvatarBig:    jd.AvatarBig,
					OpenId:       jd.OpenId,
					UnionId:      jd.UnionId,
					Email:        jd.Email,
					UserId:       jd.UserId,
					Mobile:       jd.Mobile,
					TenantKey:    jd.TenantKey,
				}
				token, tokenStr, _ := genBizJWT(&jsonRB.Data, claims.AppId, hmacSampleSecret)
				c.Set("jwtToken", tokenStr)
				c.Set("jwtClaim", token.Claims)
				c.Set("jwtClaimUat", jsonRB.Data.AccessToken)
				c.Set("refreshUserInfo", rd)
				c.Next()
			}
		} else {
			resBizJSON(c, genErrBody(ResUnauthorized))
			c.Abort()
			return
		}
	}
}
