package renders

import (
	"cangui/whatsapp/backend/models"
	"net/http"
	"strconv"
	"text/template"
	"time"
	"github.com/google/uuid"
	"github.com/gorilla/mux"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)


func Login(w http.ResponseWriter, r *http.Request){
	renderTemplate(w,"login",nil)
}
func JwtTest(w http.ResponseWriter, r *http.Request){
	renderTemplate(w,"jwt",nil)
}
func TestMessagesPages(w http.ResponseWriter, r *http.Request){
	renderTemplate(w,"test-send",nil)
}
func TestMessagesPages2(w http.ResponseWriter, r *http.Request){
	renderTemplate(w,"test",nil)
}
func AdminUserList(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var users []models.User

		if err := db.Find(&users).Error; err != nil {
			http.Error(w, "Erreur lors du chargement des utilisateurs", http.StatusInternalServerError)
			return
		}

		data := map[string]interface{}{
			"Users": users,
		}
		if _, exists := data["User"]; !exists {
			if val := r.Context().Value("ssoid"); val != nil {
				ssoid := val.(string)
				var user models.User
				if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err == nil {
					data["User"] = user
				}
			}
		}

		renderTemplate(w, "admin_users", data)
	}
}
func AdminUserEdit(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.Atoi(mux.Vars(r)["id"])
		var user models.User
		if err := db.First(&user, id).Error; err != nil {
			http.Error(w, "Utilisateur introuvable", http.StatusNotFound)
			return
		}

		data := map[string]interface{}{
			"User": user,
		}
		if _, exists := data["User"]; !exists {
			if val := r.Context().Value("ssoid"); val != nil {
				ssoid := val.(string)
				var user models.User
				if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err == nil {
					data["User"] = user
				}
			}
		}
		renderTemplate(w, "admin_user_edit", data)
	}
}
func CreateUserHandler(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			http.Error(w, "Formulaire invalide", http.StatusBadRequest)
			return
		}

		email := r.FormValue("email")
		password := r.FormValue("password")
		role := r.FormValue("role")
		monthlyCreditsStr := r.FormValue("monthly_credits")
		waToken := r.FormValue("whatsapp_token")
		waPhoneID := r.FormValue("whatsapp_phone_number_id")

		if email == "" || password == "" {
			http.Error(w, "Email et mot de passe requis", http.StatusBadRequest)
			return
		}

		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
		if err != nil {
			http.Error(w, "Erreur hash mot de passe", http.StatusInternalServerError)
			return
		}

		monthlyCredits := uint(100)
		if monthlyCreditsStr != "" {
			if val, err := strconv.Atoi(monthlyCreditsStr); err == nil {
				monthlyCredits = uint(val)
			}
		}

		newUser := models.User{
			Email:                email,
			Password:             string(hashedPassword),
			Role:                 models.UserRole(role),
			SSOID:                uuid.New().String(),
			IsActive:             true,
			MonthlyCredits:       monthlyCredits,
			CurrentMonthCredits:  monthlyCredits,
			WhatsappToken:        waToken,
			WhatsappPhoneNumberID: waPhoneID,
		}

		if err := db.Create(&newUser).Error; err != nil {
			http.Error(w, "Erreur lors de la création", http.StatusInternalServerError)
			return
		}

		w.Header().Set("HX-Trigger", "userCreated")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("<article class='message is-success'><div class='message-body'>Utilisateur créé avec succès.</div></article>"))
	}
}
func AdminUserCreateForm(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		data := map[string]interface{}{
			"User": "",
		}
		if val := r.Context().Value("ssoid"); val != nil {
			ssoid := val.(string)
			var user models.User
			if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err == nil {
				data["User"] = user
			}
		}
		renderTemplate(w, "admin_user_create", data)
	}
}
func AdminUserCreate(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			http.Error(w, "Formulaire invalide", http.StatusBadRequest)
			return
		}

		email := r.FormValue("email")
		password := r.FormValue("password")
		role := models.UserRole(r.FormValue("role"))

		hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
		if err != nil {
			http.Error(w, "Erreur hash", http.StatusInternalServerError)
			return
		}

		ssoid := "sso_" + uuid.New().String()
		user := models.User{
			Email:    email,
			Password: string(hashed),
			Role:     role,
			IsActive: true,
			SSOID:    ssoid,
		}

		if err := db.Create(&user).Error; err != nil {
			http.Error(w, "Erreur enregistrement", http.StatusInternalServerError)
			return
		}

		w.Header().Set("HX-Trigger", `{"userCreated":"Utilisateur créé avec succès"}`)
		w.Header().Set("HX-Remove", "true") // cache le form
		renderPartial(w, "admin_user_row", map[string]interface{}{"User": user})
	}
}

func AdminUserEditForm(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]

		var user models.User
		if err := db.First(&user, id).Error; err != nil {
			http.Error(w, "Utilisateur introuvable", http.StatusNotFound)
			return
		}

		data := map[string]interface{}{
			"User": user,
		}
		if _, exists := data["User"]; !exists {
			if val := r.Context().Value("ssoid"); val != nil {
				ssoid := val.(string)
				var user models.User
				if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err == nil {
					data["User"] = user
				}
			}
		}

		renderTemplate(w, "admin_user_edit", data)
	}
}
func AdminUserUpdate(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]

		var user models.User
		if err := db.First(&user, id).Error; err != nil {
			http.Error(w, "Utilisateur introuvable", http.StatusNotFound)
			return
		}

		if err := r.ParseForm(); err != nil {
			http.Error(w, "Formulaire invalide", http.StatusBadRequest)
			return
		}

		email := r.FormValue("email")
		password := r.FormValue("password")
		role := r.FormValue("role")
		isActive := r.FormValue("is_active") == "on"
		waToken := r.FormValue("whatsapp_token")
		waPhoneID := r.FormValue("whatsapp_phone_number_id")
		monthlyCreditsStr := r.FormValue("monthly_credits")

		user.Email = email
		user.Role = models.UserRole(role)
		user.IsActive = isActive
		user.WhatsappToken = waToken
		user.WhatsappPhoneNumberID = waPhoneID

		if monthlyCreditsStr != "" {
			if val, err := strconv.Atoi(monthlyCreditsStr); err == nil {
				user.MonthlyCredits = uint(val)
			}
		}

		if password != "" {
			hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
			if err != nil {
				http.Error(w, "Erreur de hachage du mot de passe", http.StatusInternalServerError)
				return
			}
			user.Password = string(hash)
		}

		if err := db.Save(&user).Error; err != nil {
			http.Error(w, "Erreur lors de la mise à jour", http.StatusInternalServerError)
			return
		}

		w.Header().Set("HX-Trigger", "userUpdated")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("<article class='message is-success'><div class='message-body'>Utilisateur mis à jour avec succès.</div></article>"))
	}
}
func AdminConversationPage(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		idStr := mux.Vars(r)["id"]
	

		data := map[string]interface{}{
			"UserID": idStr,
		}
		if _, exists := data["User"]; !exists {
			if val := r.Context().Value("ssoid"); val != nil {
				ssoid := val.(string)
				var user models.User
				if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err == nil {
					data["User"] = user
				}
			}
		}
		renderTemplate(w, "adminconversations", data)
	}
}
func AdminConversationRows(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 1. Récupérer SSOID depuis le contexte
		val := r.Context().Value("ssoid")
		ssoid, ok := val.(string)
		if !ok || ssoid == "" {
			http.Error(w, "Non authentifié", http.StatusUnauthorized)
			return
		}

		// 2. Trouver l'utilisateur
		var currentUser models.User
		if err := db.Where("sso_id = ?", ssoid).First(&currentUser).Error; err != nil {
			http.Error(w, "Utilisateur introuvable", http.StatusUnauthorized)
			return
		}

		// 3. Récupération des filtres
		idStr := mux.Vars(r)["id"]
		id, _ := strconv.Atoi(idStr)
		typeFilter := r.URL.Query().Get("type")
		dateFilter := r.URL.Query().Get("filter")

		var fromDate time.Time
		now := time.Now()
		switch dateFilter {
		case "today":
			fromDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
		case "week":
			fromDate = now.AddDate(0, 0, -7)
		default:
			fromDate = time.Time{}
		}

		var convs []models.Conversation
		query := db.Model(&models.Conversation{})

		// 4. ADMIN → tout ou par utilisateur ciblé
		if currentUser.Role != models.ROLE_ADMIN {
			query = query.Where("user_id = ?", currentUser.ID)
		} else if id > 0 {
			query = query.Where("user_id = ?", id)
		}

		if !fromDate.IsZero() {
			query = query.Where("created_at >= ?", fromDate)
		}
		if typeFilter != "" {
			query = query.Where("type = ?", typeFilter)
		}

		query.Order("created_at desc").Find(&convs)

		data := map[string]interface{}{
			"Conversations": convs,
			"UserID":        idStr,
		}
		renderPartial(w, "admin_conversations_rows", data)
	}
}
func AdminConversationThread(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		idStr := mux.Vars(r)["id"]
		id, _ := strconv.Atoi(idStr)

		var convs []models.Conversation
		db.Where("user_id = ?", id).Order("created_at asc").Find(&convs)

		data := map[string]interface{}{
			"Conversations": convs,
			"UserID":        idStr,
		}
		renderPartial(w, "admin_conversations_thread", data)
	}
}
func Dashboard(db *gorm.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		val := r.Context().Value("ssoid")
		ssoid, ok := val.(string)
		if !ok || ssoid == "" {
			http.Error(w, "Utilisateur non authentifié", http.StatusUnauthorized)
			return
		}
				

		var user models.User
		if err := db.Where("sso_id = ?", ssoid).First(&user).Error; err != nil {
			http.Error(w, "Utilisateur introuvable", http.StatusUnauthorized)
			return
		}

		filter := r.URL.Query().Get("filter")
		var fromDate time.Time
		now := time.Now()

		switch filter {
		case "today":
			fromDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
		case "week":
			fromDate = now.AddDate(0, 0, -7)
		default:
			fromDate = time.Time{} // zero time: no filter
		}

		var totalUsers int64
		var totalCredits uint
		var totalConversations int64
		var conversations []models.Conversation

		if user.Role == models.ROLE_ADMIN {
			db.Model(&models.User{}).Count(&totalUsers)
			db.Model(&models.Consumption{}).Select("SUM(credits_used)").Scan(&totalCredits)
			db.Model(&models.Conversation{}).Where("created_at >= ?", fromDate).Count(&totalConversations)
			db.Where("created_at >= ?", fromDate).Order("created_at desc").Limit(10).Find(&conversations)
		} else {
			db.Model(&models.User{}).Where("id = ?", user.ID).Count(&totalUsers)
			db.Model(&models.Consumption{}).Where("user_id = ?", user.ID).Select("SUM(credits_used)").Scan(&totalCredits)
			db.Model(&models.Conversation{}).Where("user_id = ? AND created_at >= ?", user.ID, fromDate).Count(&totalConversations)
			db.Where("user_id = ? AND created_at >= ?", user.ID, fromDate).Order("created_at desc").Limit(10).Find(&conversations)
		}

		data := map[string]interface{}{
			"User": user,
			"Stats": map[string]interface{}{
				"TotalUsers":         totalUsers,
				"TotalCreditsUsed":  totalCredits,
				"TotalConversations": totalConversations,
			},
			"Conversations": conversations,
		}

		renderTemplate(w, "dashboard", data)
	}
}



func renderTemplate(w http.ResponseWriter, templ string, data map[string]interface{}) {
    t, err := template.ParseFiles(
		"./frontend/templates/head.pages.tmpl",
		"./frontend/templates/sidebar.pages.tmpl",
		"./frontend/templates/" + templ + ".pages.tmpl",
    )

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // Exécutez explicitement le template principal
    err = t.ExecuteTemplate(w, templ+".pages.tmpl", data)

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func renderPartial(w http.ResponseWriter, templ string, data map[string]interface{}) {
    t, err := template.ParseFiles("./frontend/templates/" + templ + ".pages.tmpl")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    err = t.Execute(w, data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

