package jwt

import (
	connection "cf-capital/module_server/handlers/connection"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"
	aes "cf-capital/module_server/handlers/aes"
	log "github.com/rs/zerolog/log"

	"github.com/golang-jwt/jwt/v4"
)

var hmacSampleSecret []byte

func Token(id int) string {

	loc, _ := time.LoadLocation("Asia/Kolkata")
	now := time.Now().In(loc)

	hmacSampleSecret = []byte("4A24E4AFE9B75518794B6A0")
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"id":  id,
		"iat": now.Unix(),                        //current
		"nbf": now.Add(-10 * time.Minute).Unix(), // -10minutes
		"exp": now.AddDate(0, 0, 1).Unix(),       // +1day
	})

	tokenString, err := token.SignedString(hmacSampleSecret)

	if err != nil {
		log.Panic().Err(err).Msg(err.Error())
		// log.Panic(err)
	}
	return tokenString
}

func Verify(jToken string) ([]byte, error) {

	resp := make(map[string]string)
	splitToken := strings.Split(jToken, "Bearer ")
	log.Print(len(splitToken))
	if len(splitToken) <= 1 {
		log.Print("f")
		resp["status"] = "FAIL"
		resp["message"] = "Authorization header is missing"
		jsonRes, errJson := json.Marshal(resp)
		if errJson != nil {
			log.Print(errJson.Error())
		}
		return jsonRes, errors.New(resp["message"])
	}
	tokenString := splitToken[1]

	hmacSampleSecret = []byte("4A24E4AFE9B75518794B6A0")

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		//validate the alg is what you expect:
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		}

		return hmacSampleSecret, nil
	})

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		//log.Print(claims["id"], claims["iat"], claims["nbf"], claims["exp"])
		resp = getUser(fmt.Sprint(claims["id"]))

		if len(resp) == 0 {
			log.Print("test")
			resp["status"] = "FAIL"
			resp["message"] = "Unauthorized access"
			jsonRes, errJson := json.Marshal(resp)
			if errJson != nil {
				log.Print(err.Error())
			}
			return jsonRes, errors.New(resp["message"])
		}

		jsonRes, errJson := json.Marshal(resp)
		if errJson != nil {
			log.Print(err.Error())
		}
		return jsonRes, nil
	} else {
		resp["status"] = "FAIL"
		resp["message"] = "Unauthorized access"
		jsonRes, errJson := json.Marshal(resp)
		if errJson != nil {
			log.Print(err.Error())
		}
		return jsonRes, err
	}
}

func getUser(id string) map[string]string {

	tx, _, db := connection.Connect()

	log.Print(id)
	row := tx.QueryRow("select CONCAT(COALESCE(`first_name`,''), ' ', COALESCE(`middle_name`,''), ' ', COALESCE(`last_name`,'')) as name, COALESCE(`mobile_number`,'') as mobile_number, COALESCE(`email`,''), COALESCE(`lb_user_id`, ''), COALESCE(`user_type`, '') from users where id = ? limit 1", id)

	var name string
	var phone string
	var email string
	var lb_user_id string
	var user_type string

	resp := make(map[string]string)
	err := row.Scan(&name, &phone, &email, &lb_user_id, &user_type)
	if err != nil {
		tx.Rollback()
		log.Print(err.Error())
		return resp
	}

	log.Print("AuthID:", id)
	resp["id"] = id
	resp["name"] = strings.Join(strings.Fields(name), " ")
	resp["phone"] = aes.DecryptData(phone)
	resp["email"] = aes.DecryptData(email)
	resp["lb_user_id"] = lb_user_id
	resp["user_type"] = user_type

	connection.Close(tx, db)
	return resp
}
