package auth

import (
	"encoding/base64"
	"encoding/json"
	"net"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/pingcap-inc/clinic/pkg/auth/api_key"
	"github.com/pingcap-inc/clinic/pkg/auth/session"
	"github.com/pingcap-inc/clinic/pkg/auth/utils"
)

type Auth struct {
	Manager       *session.SessionManager
	AllowCidrs    []*net.IPNet
	AllowEmptyIP  bool
	UseAPIGateway bool
}

func (a *Auth) MWTryAuth(c *gin.Context) {
	if a.UseAPIGateway {
		if c.GetHeader(session.AuthType) == "api-gateway" {
			c.Next()
			return
		}

		data, err := base64.StdEncoding.DecodeString(c.GetHeader(session.CtxUserKey))
		if err != nil {
			log.Error("decode user failed", zap.String("user", c.GetHeader(session.CtxUserKey)), zap.Error(err))
			utils.AuthError(c, "invalid user")
			return
		}
		var u session.CtxUser
		if err := json.Unmarshal(data, &u); err != nil {
			log.Error("decode user failed", zap.String("user", c.GetHeader(session.CtxUserKey)), zap.Error(err))
			utils.AuthError(c, "invalid user")
			return
		}

		c.Set(session.CtxUserKey, &u)
		c.Next()
		return
	}

	switch {
	case api_key.MWTryAuth(c, a.AllowCidrs, a.AllowEmptyIP):
	default:
		a.Manager.MWTryAuth(c)
	}
}
