package users

import (
	"app/shelfly/internal/models"
	"app/shelfly/query"

	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

func CreateUser(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		// Vérifier si le corps de la requête est vide
		if r.Body == nil {
			w.WriteHeader(http.StatusBadRequest)
			log.Println("Le corps de la requête est vide")
			fmt.Fprintf(w, `{"error": "Request body is empty"}`)
			return
		}

		// Vérifier le Content-Type
		if r.Header.Get("Content-Type") != "application/json" {
			w.WriteHeader(http.StatusUnsupportedMediaType)
			log.Println("Content-Type invalide. Requis: application/json")
			fmt.Fprintf(w, `{"error": "Content-Type must be application/json"}`)
			return
		}

		// Lire et décoder le JSON
		var u models.User
		if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			log.Printf("Erreur lors du décodage du JSON : %v", err)
			fmt.Fprintf(w, `{"error": "Invalid JSON format"}`)
			return
		}

		// Hacher le mot de passe de l'utilisateur
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			log.Printf("Erreur lors du hachage du mot de passe : %v", err)
			fmt.Fprintf(w, `{"error": "Failed to hash password"}`)
			return
		}

		// Remplacer le mot de passe par le hachage
		u.Password = string(hashedPassword)

		// Initialiser le query builder
		q := query.Use(db)

		// Créer l'utilisateur
		if err := q.User.Create(&u); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			log.Printf("Erreur lors de la création de l'utilisateur : %v", err)
			fmt.Fprintf(w, `{"error": "Failed to create user"}`)
			return
		}

		log.Printf("Utilisateur créé avec succès : %v", u)

		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, `{"message": "User created successfully"}`)
	}
}

func UpdateUser(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		// Vérifier si le corps de la requête est vide
		if r.Body == nil {
			w.WriteHeader(http.StatusBadRequest)
			log.Println("Le corps de la requête est vide")
			fmt.Fprintf(w, `{"error": "Request body is empty"}`)
			return
		}

		// Vérifier le Content-Type
		if r.Header.Get("Content-Type") != "application/json" {
			w.WriteHeader(http.StatusUnsupportedMediaType)
			log.Println("Content-Type invalide. Requis: application/json")
			fmt.Fprintf(w, `{"error": "Content-Type must be application/json"}`)
			return
		}

		params := mux.Vars(r)
		q := query.Use(db)
		id, err := strconv.Atoi(params["id"])
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		u := q.User
		ctx := context.Background()

		user, err := u.WithContext(ctx).Where(u.ID.Eq(uint(id))).First()
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		log.Printf("Utilisateur update avec succès : %v", user)

		// Lire et décoder le JSON
		var usr models.User
		if err := json.NewDecoder(r.Body).Decode(&usr); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			log.Printf("Erreur lors du décodage du JSON : %v", err)
			fmt.Fprintf(w, `{"error": "Invalid JSON format"}`)
			return
		}
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(usr.Password), bcrypt.DefaultCost)
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		user.Name = usr.Name
		user.Username = usr.Username
		user.Email = usr.Email
		user.Password = string(hashedPassword)

		u.Save(user)
		w.WriteHeader(http.StatusOK)

	}
}
func DeleteUser(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		// Vérifier si le corps de la requête est vide
		if r.Body == nil {
			w.WriteHeader(http.StatusBadRequest)
			log.Println("Le corps de la requête est vide")
			fmt.Fprintf(w, `{"error": "Request body is empty"}`)
			return
		}

		// Vérifier le Content-Type
		if r.Header.Get("Content-Type") != "application/json" {
			w.WriteHeader(http.StatusUnsupportedMediaType)
			log.Println("Content-Type invalide. Requis: application/json")
			fmt.Fprintf(w, `{"error": "Content-Type must be application/json"}`)
			return
		}

		params := mux.Vars(r)
		q := query.Use(db)
		id, err := strconv.Atoi(params["id"])
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		u := q.User
		ctx := context.Background()

		user, err := u.WithContext(ctx).Where(u.ID.Eq(uint(id))).First()
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		u.Delete(user)
		log.Printf("Utilisateur delete avec succès : %v", user)
		w.WriteHeader(http.StatusOK)

	}
}
func ReadAllUser(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")


		q := query.Use(db)

		data,err :=q.User.Find()
		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		log.Printf("Utilisateur read avec succès : %v", data)
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(data)

	}
}
func FindUserById (db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")


		params := mux.Vars(r)
		q := query.Use(db)
		id, err := strconv.Atoi(params["id"])
		log.Printf("Utilisateur ID avec succès : %v", id)

		if err != nil {
			//panic(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		u := q.User
		ctx := context.Background()

		user, err := u.WithContext(ctx).Where(u.ID.Eq(uint(id))).First()

		log.Printf("Utilisateur read avec succès : %v", user)
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(user)

	}}