package utils

import (
	"crypto/rand"
	"encoding/json"
	"errors"
	"math/big"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/rs/zerolog/log"
)

func GetXAuhorizationHeader(c *fiber.Ctx) string {
	return c.GetReqHeaders()[HeaderXAuthorization]
}

func GetXApiKeyHeader(c *fiber.Ctx) string {
	return c.GetReqHeaders()[HeaderXApiKey]
}

func MarshalJson(v any) string {
	json, err := json.Marshal(v)

	if err != nil {
		log.Error().Msgf("Failed to marshal json %s", err)
		return ""
	}

	return string(json)
}

func GetSessionExpiresAtTime() time.Time {
	return time.Now().Add(time.Second * SessionExpiresAtTime)
}

func IsPasswordLengthValid(password string) bool {
	lenPassword := len(password)

	if lenPassword < MinPassword || lenPassword > MaxPassword {
		log.Error().Msg("Password length not valid")
		return false
	}

	return true
}

func GenerateSession() (string, error) {
	var letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

	r := make([]byte, 36)

	for i := 0; i < 36; i++ {
		num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))

		if err != nil {
			log.Error().Msgf("Failed to session: %v", err)
			return "", err
		}

		if i == 8 || i == 13 || i == 18 || i == 23 {
			r[i] = 45
		} else {
			r[i] = letters[num.Int64()]
		}
	}

	return string(r), nil
}

func ParamsParserHelper(c *fiber.Ctx, params interface{}) error {
	if err := c.ParamsParser(params); err != nil {
		log.Error().Msgf("Failed to parse params, err: %s", err.Error())
		return errors.New("Failed to parse params")
	}

	if errValidation := ValidateStruct(params); errValidation != nil {
		log.Error().Msgf("Failed to validate params, err: %v", errValidation)
		return errors.New("Failed to validate params")
	}

	return nil
}

func BodyParserHelper(c *fiber.Ctx, body interface{}) error {
	if err := c.BodyParser(body); err != nil {
		log.Error().Msgf("Failed to parse body, err: %s", err.Error())
		return errors.New("Failed to parse body")
	}

	if errValidation := ValidateStruct(body); errValidation != nil {
		log.Error().Msgf("Failed to validate body, err: %v", errValidation)
		return errors.New("Failed to validate body")
	}

	return nil
}
