package models

import (
	"fmt"
	"net/http"
	"time"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

var (
	// JWTKey - JWTKey for r and c
	JWTKey     = "gUkXp2s5v8y/B?E(H+MbQeThVmYq3t6w"
	ConfigPath = "configs/database.json"
	Host       = "CoreStudio"
	Database   = "CoreStudio"
	Collection = "gotemplate"
)

const (
	// DefaultProjectPort -
	DefaultPort = "3000"
	PprofPort   = "6060"
)

type User struct {
	Id         string `json:"id" bson:"id"`
	UserName   string `json:"userName" bson:"userName"`
	Password   string `json:"password" bson:"password"`
	CreatedOn  int64  `json:"createdOn" bson:"createdOn"`
	CreatedBy  string `json:"createdBy" bson:"createdBy"`
	ModifiedOn int64  `json:"modifiedOn" bson:"modifiedOn"`
	ModifiedBy string `json:"modifiedBy" bson:"modifiedBy"`
}
type Employee struct {
	Name     string `json:"name"`
	Location string `json:"location"`
}
type ResponseData struct {
	Result         interface{} `json:"result"`
	Error          interface{} `json:"error"`
	ResponseHeader interface{} `json:"reponseHeader"`
	ErrorCode      int         `json:"errorCode"`
	IsCompressed   bool        `json:"isCompressed"`
	ServerTime     time.Time   `json:"serverTime"`
}

type jwtCustomClaims struct {
	LoginId   string   `json:"loginId"`
	Groups    []string `json:"groups"`
	ClientIP  string   `json:"clientIP"`
	HitsCount int      `json:"hitsCount"`
	Token     string   `json:"token"`
	Metadata  string   `json:"metadata"`
	jwt.RegisteredClaims
}

func NewInstance(userName, password, createdBy, modifiedBy string, createdOn, modifiedOn int64) User {
	return User{
		UserName:   userName,
		Password:   password,
		CreatedOn:  createdOn,
		CreatedBy:  createdBy,
		ModifiedOn: modifiedOn,
		ModifiedBy: modifiedBy,
	}
}

// GetResponseData - to get the return obj
func GetResponseData(result interface{}, errorData interface{}, errorCode int) ResponseData {
	return ResponseData{
		Result:     result,
		Error:      errorData,
		ErrorCode:  errorCode,
		ServerTime: time.Now(),
	}
}

func DecodeToken(tokenString string) error {
	claims := jwt.MapClaims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return []byte(JWTKey), nil
	})
	if err != nil {
		return err
	}
	loggermdl.LogError("token,", token)
	for key, val := range claims {
		fmt.Printf("Key: %v, value: %v\n", key, val)
	}
	return err
}

func GenerateTokenForLogin(c *gin.Context) {
	var loginData jwtCustomClaims
	err := c.Bind(&loginData)
	if err != nil {
		loggermdl.LogError("Error binding Json data")
	}
	loginId := loginData.LoginId
	groups := loginData.Groups
	clientIp := loginData.ClientIP
	metadata := loginData.Metadata
	expiresAt := time.Hour * 24
	token, err := GenerateToken(loginId, groups, metadata, clientIp, expiresAt)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"token": token})
}

func GenerateToken(loginId string, groups []string, metadata string, clientIP string, expiresAt time.Duration) (string, error) {
	claims := jwtCustomClaims{
		LoginId:  loginId,
		Groups:   groups,
		Metadata: metadata,
		ClientIP: clientIP,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(expiresAt)),
		}}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	mySigningKey := []byte(JWTKey)
	signedToken, err := token.SignedString([]byte(mySigningKey))
	if err != nil {
		return "Error signing token.", err
	} else {
		loggermdl.LogError("Signed Token", signedToken)
	}

	err = DecodeToken(signedToken)
	if err != nil {
		loggermdl.LogError("Error decoding")
	} else {
		loggermdl.LogError("Decode successful.")
	}
	return signedToken, nil
}