package middleware

import (
	"cargo-erp-backend/pkg/helpers"
	"cargo-erp-backend/pkg/response"
	"context"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
)

type AuthMiddlewareInterface interface {
	Check() gin.HandlerFunc
}
type AuthMiddleware struct {
	Helper helpers.HelperInterface
}

func NewAuthMiddleware(helper helpers.HelperInterface) AuthMiddlewareInterface {
	return &AuthMiddleware{
		Helper: helper,
	}
}
func (m *AuthMiddleware) Check() gin.HandlerFunc {
	return func(c *gin.Context) {
		// rechecking auth header
		authHeader := c.GetHeader("Authorization")
		authData := ""
		authKey := ""
		err_auth_header := false
		if authHeader == "" {
			err_auth_header = true
		}

		parts := strings.Fields(authHeader)
		token_string := ""
		if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
			err_auth_header = true
		} else {
			token_string = parts[1]
		}
		if err_auth_header {
			cookieName := fmt.Sprintf("%v", m.Helper.Config().Get("cookie.name"))
			value, err := c.Cookie(cookieName)
			if err != nil {
				response.Error(c, http.StatusUnauthorized, "Unauthorized")
				c.Abort()
				return
			}
			if len(parts) > 1 && len(value) > 0 && parts[1] != value {
				response.Error(c, http.StatusUnauthorized, "Unauthorized")
				c.Abort()
				return
			}
			token_string = value
		}
		if token_string == "" {
			response.Error(c, http.StatusUnauthorized, "Unauthorized")
			c.Abort()
			return
		}
		ctx := context.Background()
		redis_exist := make(map[string]string)
		m.Helper.Log().Info("session_login : " + token_string)
		iter := m.Helper.GetRedis("slave").Scan(ctx, 0, "session_login:*:"+token_string, 1000).Iterator()
		for iter.Next(ctx) {
			keys := iter.Val()

			value, err := m.Helper.GetRedis("slave").Get(ctx, keys).Result()
			if err != nil {
				if err == redis.Nil {
					continue
				}

			}
			redis_exist[keys] = value
		}
		if err := iter.Err(); err != nil {
			response.Error(c, http.StatusUnauthorized, "Unauthorized")
			c.Abort()
			return
		}
		if len(redis_exist) != 1 {
			response.Error(c, http.StatusUnauthorized, "Unauthorized")
			c.Abort()
			return
		}
		for k, v := range redis_exist {
			authData = v
			authKey = k
		}
		m.Helper.Log().Info("Set Auth : " + authData)
		c.Set("auth", authData)
		c.Set("auth_key", authKey)
		c.Next()
	}
}
