package handlers

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

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func setupTestStatusRouter() (*gin.Engine, *StatusHandler) {
	gin.SetMode(gin.TestMode)
	router := gin.New()

	logger := zap.NewNop()
	db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	handler := NewStatusHandler(db, logger, nil, "", "", "1.0.0", "abc123", "2024-01-01", "test")

	router.GET("/status", handler.GetStatus)
	router.GET("/system/info", handler.GetSystemInfo)

	return router, handler
}

func TestStatusHandler_GetStatus_Success(t *testing.T) {
	// Setup
	router, _ := setupTestStatusRouter()

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

	// Assert
	assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusServiceUnavailable)

	var apiResponse APIResponse
	err := json.Unmarshal(w.Body.Bytes(), &apiResponse)
	assert.NoError(t, err)
	assert.True(t, apiResponse.Success)

	var response StatusResponse
	responseBytes, _ := json.Marshal(apiResponse.Data)
	json.Unmarshal(responseBytes, &response)
	assert.Contains(t, response.Services, "database")
	assert.Contains(t, response.Services, "redis")
	assert.Equal(t, "1.0.0", response.Version)
	assert.Equal(t, "abc123", response.GitCommit)
}

func TestStatusHandler_GetStatus_WithEnvironment(t *testing.T) {
	// Setup
	gin.SetMode(gin.TestMode)
	router := gin.New()

	logger := zap.NewNop()
	db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	handler := NewStatusHandler(db, logger, nil, "", "", "1.0.0", "abc123", "2024-01-01", "production")

	router.GET("/status", handler.GetStatus)

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

	// Assert
	assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusServiceUnavailable)

	var apiResponse APIResponse
	err := json.Unmarshal(w.Body.Bytes(), &apiResponse)
	assert.NoError(t, err)

	var response StatusResponse
	responseBytes, _ := json.Marshal(apiResponse.Data)
	json.Unmarshal(responseBytes, &response)
	assert.Equal(t, "production", response.Environment)
}

func TestStatusHandler_GetSystemInfo_Success(t *testing.T) {
	// Setup
	router, _ := setupTestStatusRouter()

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

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

	var apiResponse APIResponse
	err := json.Unmarshal(w.Body.Bytes(), &apiResponse)
	assert.NoError(t, err)

	var response map[string]interface{}
	responseBytes, _ := json.Marshal(apiResponse.Data)
	json.Unmarshal(responseBytes, &response)
	assert.Contains(t, response, "uptime_seconds")
	assert.Contains(t, response, "memory")
	assert.Contains(t, response, "goroutines")

	memory := response["memory"].(map[string]interface{})
	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")
}
