package controllers

import (
	"api/database"
	"api/models"
	"api/utils"
	"os"
	"strconv"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gofiber/fiber/v2"
	"golang.org/x/crypto/bcrypt"
)

// Login - Login. Returns a JWT token on the response body
func Login(c *fiber.Ctx) error {

	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return fiber.ErrBadRequest
	}

	var user models.User

	database.DB.Where("email = ?", data["email"]).First(&user)

	if user.Id == 0 {
		return fiber.ErrNotFound
	}

	if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil {
		return fiber.ErrUnauthorized
	}

	type customClaims struct {
		Userid string `json:"user"`
		jwt.StandardClaims
	}

	tok := customClaims{
		Userid: strconv.Itoa(int(user.Id)),
		StandardClaims: jwt.StandardClaims{
			Issuer:    strconv.Itoa(int(user.Id)),
			ExpiresAt: time.Now().Add(time.Hour * 1).Unix(),
		},
	}

	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, tok)

	token, err := claims.SignedString([]byte(os.Getenv("API_SECRET")))
	if err != nil {
		return fiber.ErrInternalServerError
	}

	return c.JSON(fiber.Map{
		"userId":   user.Id,
		"userType": user.UserType,
		"userName": user.Name,
		"token":    token})
}

// Register/AdUser - Adds or register a user to the database
func AddUser(c *fiber.Ctx) error {

	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return fiber.ErrBadRequest
	}

	// If I don't receive an auth field in the request, I need to verify if the sender is logged
	if data["auth"] == "" {
		_, err := utils.ProcessToken(c)
		if err != nil {
			return fiber.ErrUnauthorized
		}
	}

	if data["name"] == "" || data["email"] == "" || data["password"] == "" || data["channel"] == "" {
		return fiber.ErrBadRequest
	}

	passwd, _ := utils.HashPassword(data["password"])

	user := models.User{
		Name:        data["name"],
		Email:       data["email"],
		CompanyName: data["companyname"],
		Password:    passwd,
		Channel:     data["channel"],
		UserType:    data["usertype"],
		Blocked:     "N",
		Cancelled:   "N",
		CreatedBy:   data["creator"],
	}

	database.DB.Create(&user)

	if user.Id == 0 {
		return fiber.ErrNotAcceptable
	}

	return c.JSON(fiber.Map{
		"user": user,
	})
}

// GetOwnUser - Returns the current	user
func GetOwnUser(c *fiber.Ctx) error {

	var user models.User

	userCode, err := utils.ProcessToken(c)
	if err != nil {
		return fiber.ErrUnauthorized
	}

	database.DB.Where("id = ?", userCode).First(&user)

	if user.Id == 0 {
		return fiber.ErrUnauthorized
	}

	return c.JSON(fiber.Map{
		"user": user,
	})
}

// GetAllUsers - Returns all users
func GetAllUsers(c *fiber.Ctx) error {

	var users []models.User

	_, err := utils.ProcessToken(c)
	if err != nil {
		return fiber.ErrUnauthorized
	}

	database.DB.Find(&users)

	if len(users) == 0 {
		return fiber.ErrNotFound
	}

	return c.JSON(users)
}

func WixIntegration(c *fiber.Ctx) error {
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return fiber.ErrBadRequest
	}

	utils.PrettyPrintJson(data)

	return c.JSON(data)
}
