package handlers

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestSystemMetrics_Success(t *testing.T) {
	// Setup
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.GET("/system/metrics", SystemMetrics)

	// Execute
	req, _ := http.NewRequest("GET", "/system/metrics", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	// Assert
	assert.Equal(t, http.StatusOK, w.Code)

	var response map[string]interface{}
	err := json.Unmarshal(w.Body.Bytes(), &response)
	assert.NoError(t, err)

	// Action 1.3.2.1: Response now uses wrapped format
	assert.True(t, response["success"].(bool))
	data, ok := response["data"].(map[string]interface{})
	assert.True(t, ok, "Response should have data field")

	// Verify structure
	assert.Contains(t, data, "timestamp")
	assert.Contains(t, data, "memory")
	assert.Contains(t, data, "goroutines")
	assert.Contains(t, data, "cpu_count")

	// Verify memory structure
	memory, ok := data["memory"].(map[string]interface{})
	assert.True(t, ok)
	assert.Contains(t, memory, "alloc_mb")
	assert.Contains(t, memory, "total_alloc_mb")
	assert.Contains(t, memory, "sys_mb")
	assert.Contains(t, memory, "num_gc")

	// Verify numeric values
	assert.IsType(t, float64(0), data["goroutines"])
	assert.IsType(t, float64(0), data["cpu_count"])
}

func TestSystemMetrics_MultipleRequests(t *testing.T) {
	// Setup
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.GET("/system/metrics", SystemMetrics)

	// Execute multiple requests
	for i := 0; i < 3; i++ {
		req, _ := http.NewRequest("GET", "/system/metrics", nil)
		w := httptest.NewRecorder()
		router.ServeHTTP(w, req)

		// Assert
		assert.Equal(t, http.StatusOK, w.Code)

		var response map[string]interface{}
		err := json.Unmarshal(w.Body.Bytes(), &response)
		assert.NoError(t, err)
		// Action 1.3.2.1: Response now uses wrapped format
		assert.True(t, response["success"].(bool))
		data, ok := response["data"].(map[string]interface{})
		assert.True(t, ok)
		assert.Contains(t, data, "memory")
		assert.Contains(t, data, "goroutines")
	}
}

func TestBToMb_Conversion(t *testing.T) {
	tests := []struct {
		name     string
		input    uint64
		expected uint64
	}{
		{"Zero bytes", 0, 0},
		{"1 MB", 1024 * 1024, 1},
		{"10 MB", 10 * 1024 * 1024, 10},
		{"100 MB", 100 * 1024 * 1024, 100},
		{"Less than 1 MB", 512 * 1024, 0},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := bToMb(tt.input)
			assert.Equal(t, tt.expected, result)
		})
	}
}
