package handlers_test

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
	"cangui/whatsapp/backend/handlers"
	"cangui/whatsapp/backend/models"
	"github.com/gorilla/mux"
	"github.com/stretchr/testify/assert"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func initTestDB() *gorm.DB {
	database, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	database.AutoMigrate(&models.User{}, &models.Consumption{}, &models.MonthlyConsumption{}, &models.Conversation{})
	return database
}

func createTestUser(db *gorm.DB) models.User {
	hash, _ := bcrypt.GenerateFromPassword([]byte("testpass"), bcrypt.DefaultCost)
	user := models.User{
		Email: "test@example.com",
		Password: string(hash),
		SSOID: "ssoid123",
		Role: models.ROLE_ADMIN,
		IsActive: true,
		WhatsappToken: "test-token",
		WhatsappPhoneNumberID: "123456",
	}
	db.Create(&user)
	return user
}

func TestCreateUser(t *testing.T) {
	db := initTestDB()
	h := handlers.CreateUser(db)

	user := models.User{
		Email: "new@example.com",
		Password: "newpass",
		SSOID: "newssoid",
		Role: models.ROLE_CLIENT,
	}
	body, _ := json.Marshal(user)
	r := httptest.NewRequest("POST", "/api/user/create", bytes.NewReader(body))
	r.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()

	h(w, r)
	assert.Equal(t, http.StatusOK, w.Code)
}

func TestLoginHandler_Invalid(t *testing.T) {
	db := initTestDB()
	h := handlers.LoginHandler(db)
	r := httptest.NewRequest("POST", "/api/login", bytes.NewReader([]byte(`{}`)))
	r.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	h(w, r)
	assert.Equal(t, http.StatusUnauthorized, w.Code)
}

func TestSendWhatsAppMessage_Unauthorized(t *testing.T) {
	db := initTestDB()
	h := handlers.SendWhatsAppMessage(db)
	r := httptest.NewRequest("POST", "/api/message/send", nil)
	w := httptest.NewRecorder()
	h(w, r)
	assert.Equal(t, http.StatusUnauthorized, w.Code)
}

func TestBuildMessageFromPayload_Text(t *testing.T) {
	payload := map[string]interface{}{
		"to": "33600000000",
		"type": "text",
		"text": map[string]interface{}{"body": "Bonjour"},
	}
	msg, err := models.BuildMessageFromPayload(payload)
	assert.NoError(t, err)
	assert.NotNil(t, msg)
}

func TestBuildMessageFromPayload_Invalid(t *testing.T) {
	payload := map[string]interface{}{
		"to": "33600000000",
		"type": "unknown",
	}
	_, err := models.BuildMessageFromPayload(payload)
	assert.Error(t, err)
}

func TestGetAllUsers(t *testing.T) {
	db := initTestDB()
	createTestUser(db)
	h := handlers.GetAllUsers(db)
	w := httptest.NewRecorder()
	r := httptest.NewRequest("GET", "/api/user/all", nil)
	h(w, r)
	assert.Equal(t, http.StatusOK, w.Code)
}

func TestGetUserByID(t *testing.T) {
	db := initTestDB()
	user := createTestUser(db)
	h := handlers.GetUserByID(db)
	r := httptest.NewRequest("GET", "/api/user/1", nil)
	r = mux.SetURLVars(r, map[string]string{"id": "1"})
	w := httptest.NewRecorder()
	h(w, r)
	assert.Equal(t, http.StatusOK, w.Code)
	var u models.User
	json.Unmarshal(w.Body.Bytes(), &u)
	assert.Equal(t, user.Email, u.Email)
}

func TestUpdateUser(t *testing.T) {
	db := initTestDB()
	createTestUser(db)
	h := handlers.UpdateUser(db)

	updated := map[string]interface{}{
		"email": "updated@example.com",
		"role": "ADMIN",
		"is_active": true,
	}
	body, _ := json.Marshal(updated)
	r := httptest.NewRequest("PUT", "/api/user/update/1", bytes.NewReader(body))
	r = mux.SetURLVars(r, map[string]string{"id": "1"})
	r.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	h(w, r)
	assert.Equal(t, http.StatusOK, w.Code)
}

func TestDeleteUser(t *testing.T) {
	db := initTestDB()
	createTestUser(db)
	h := handlers.DeleteUser(db)
	r := httptest.NewRequest("DELETE", "/api/user/delete/1", nil)
	r = mux.SetURLVars(r, map[string]string{"id": "1"})
	w := httptest.NewRecorder()
	h(w, r)
	assert.Equal(t, http.StatusNoContent, w.Code)
}
