package jwt

import (
	"cargo-erp-backend/internal/config"
	"fmt"
	"strconv"
	"time"

	"github.com/golang-jwt/jwt/v4"
	"go.uber.org/zap"
)

type JWTinterface interface {
	GenerateToken(secret string) (string, error)
	VerifyToken(tokenString string) (*Claims, error)
}
type JWT struct {
	Config config.ConfigInterface
	Log    *zap.Logger
}

func NewJWT(config config.ConfigInterface, logger *zap.Logger) JWTinterface {
	return &JWT{
		Config: config,
		Log:    logger,
	}
}

type Claims struct {
	UserID string `json:"uid"`
	jwt.RegisteredClaims
}

func (j *JWT) GenerateToken(tokenUser string) (string, error) {
	secret := fmt.Sprintf("%v", j.Config.Get("jwt.secret"))
	expiry_time_string := fmt.Sprintf("%v", j.Config.Get("jwt.expiry_time"))
	expiry_time, err := strconv.Atoi(expiry_time_string)
	if err != nil {
		return "", err
	}
	claims := Claims{
		UserID: tokenUser,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:   "cargo-platform",
			Subject:  tokenUser,
			IssuedAt: jwt.NewNumericDate(time.Now()),
			ExpiresAt: jwt.NewNumericDate(
				time.Now().Add(time.Duration(expiry_time) * time.Second),
			),
		},
	}

	token := jwt.NewWithClaims(
		jwt.SigningMethodHS256,
		claims,
	)
	return token.SignedString([]byte(secret))
}
func (j *JWT) VerifyToken(tokenString string) (*Claims, error) {
	secret := fmt.Sprintf("%v", j.Config.Get("jwt.secret"))
	token, err := jwt.ParseWithClaims(
		tokenString,
		&Claims{},
		func(token *jwt.Token) (interface{}, error) {

			if token.Method != jwt.SigningMethodHS256 {
				return nil, fmt.Errorf("invalid signing method")
			}

			return []byte(secret), nil
		},
	)

	if err != nil {
		return nil, err
	}

	claims, ok := token.Claims.(*Claims)

	if !ok || !token.Valid {
		return nil, fmt.Errorf("invalid token")
	}

	return claims, nil
}
