package controllers

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"

	"GoMembership/internal/models"
	"GoMembership/internal/services"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
)

// Mock Repository
type MockLicenceRepo struct {
	mock.Mock
}

func (m *MockLicenceRepo) GetAllCategories() ([]models.Category, error) {
	args := m.Called()
	categories, _ := args.Get(0).([]models.Category) // Safe type assertion
	return categories, args.Error(1)
}

func (r *MockLicenceRepo) FindCategoriesByIDs(ids []uint) ([]models.Category, error) {
	return []models.Category{}, nil
}

func (r *MockLicenceRepo) FindCategoryByName(categoryName string) (models.Category, error) {
	return models.Category{}, nil
}

func TestGetAllCategories_Success(t *testing.T) {
	gin.SetMode(gin.TestMode)

	// Mock repository
	mockRepo := new(MockLicenceRepo)
	expectedCategories := []models.Category{
		{ID: 1, Name: "Category A"},
		{ID: 2, Name: "Category B"},
	}
	mockRepo.On("GetAllCategories").Return(expectedCategories, nil)

	// Create LicenceService with mocked repository
	service := &services.LicenceService{Repo: mockRepo}

	// Create controller with service
	lc := &LicenceController{Service: *service}

	// Setup router and request
	router := gin.Default()
	router.GET("/licence/categories", lc.GetAllCategories)

	w := httptest.NewRecorder()
	req, _ := http.NewRequest(http.MethodGet, "/licence/categories", nil)
	router.ServeHTTP(w, req)

	// Assertions
	assert.Equal(t, http.StatusOK, w.Code)
	assert.JSONEq(t, `{"licence_categories":[{"id":1,"category":"Category A"},{"id":2,"category":"Category B"}]}`, w.Body.String())

	mockRepo.AssertExpectations(t)
}

func TestGetAllCategories_Error(t *testing.T) {
	gin.SetMode(gin.TestMode)

	// Mock repository
	mockRepo := new(MockLicenceRepo)
	mockRepo.On("GetAllCategories").Return(nil, errors.New("database error"))

	// Create LicenceService with mocked repository
	service := &services.LicenceService{Repo: mockRepo}

	// Create controller with service
	lc := &LicenceController{Service: *service}

	// Setup router and request
	router := gin.Default()
	router.GET("/licence/categories", lc.GetAllCategories)

	w := httptest.NewRecorder()
	req, _ := http.NewRequest(http.MethodGet, "/licence/categories", nil)
	router.ServeHTTP(w, req)

	// Assertions
	assert.Equal(t, http.StatusInternalServerError, w.Code)
	assert.Contains(t, w.Body.String(), "server.error.internal_server_error")

	mockRepo.AssertExpectations(t)
}
