// >>> VEZA:BEGIN api_health_test.go
package integration

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

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

	"veza-backend-api/internal/api"
	"veza-backend-api/internal/config"
	"veza-backend-api/internal/handlers"
)

// setupTestRouter crée un router de test minimal
func setupTestRouter() *gin.Engine {
	gin.SetMode(gin.TestMode)
	router := gin.New()

	// Créer un handler simple pour /health (utiliser Check qui retourne {status: "ok"})
	healthHandler := handlers.NewHealthHandlerSimple(nil)
	router.GET("/health", healthHandler.Check)
	router.GET("/api/v1/health", healthHandler.Check)

	return router
}

// TestAPIHealth tests the health endpoint
func TestAPIHealth(t *testing.T) {
	router := setupTestRouter()

	req := httptest.NewRequest("GET", "/health", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

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

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

	// Le format standardisé retourne {success: true, data: {status: "ok"}}
	if data, ok := response["data"].(map[string]interface{}); ok {
		assert.Equal(t, "ok", data["status"])
	} else {
		// Fallback pour format simple (si handler retourne directement)
		status, ok := response["status"]
		assert.True(t, ok, "Response should have status field: %v", response)
		assert.Contains(t, []interface{}{"ok", "healthy"}, status, "Status should be 'ok' or 'healthy'")
	}
}

// TestAPIHealthV1 tests the v1 health endpoint
func TestAPIHealthV1(t *testing.T) {
	router := setupTestRouter()

	req := httptest.NewRequest("GET", "/api/v1/health", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

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

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

	// Le format standardisé retourne {success: true, data: {status: "ok"}}
	if data, ok := response["data"].(map[string]interface{}); ok {
		assert.Equal(t, "ok", data["status"])
	} else {
		// Fallback pour format simple (si handler retourne directement)
		status, ok := response["status"]
		assert.True(t, ok, "Response should have status field: %v", response)
		assert.Contains(t, []interface{}{"ok", "healthy"}, status, "Status should be 'ok' or 'healthy'")
	}
}

// TestAPIStatus tests the status endpoint
func TestAPIStatus(t *testing.T) {
	// Skip si pas de DB configurée
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	// Créer une config de test
	cfg, err := config.NewConfig()
	if err != nil {
		t.Skipf("Skipping test: cannot create config: %v", err)
		return
	}

	// Créer un router avec la config
	gin.SetMode(gin.TestMode)
	router := gin.New()
	apiRouter := api.NewAPIRouter(cfg.Database, cfg)
	apiRouter.Setup(router)

	req := httptest.NewRequest("GET", "/api/v1/status", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

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

	var response handlers.StatusResponse
	err = json.Unmarshal(w.Body.Bytes(), &response)
	assert.NoError(t, err)
	assert.NotEmpty(t, response.Status)
	assert.GreaterOrEqual(t, response.UptimeSec, int64(0))
	assert.NotNil(t, response.Services)
}

// TestAPIStatusDegraded tests status endpoint when a service is down
func TestAPIStatusDegraded(t *testing.T) {
	// Ce test nécessite un mock ou une configuration spécifique
	// Pour l'instant, on vérifie juste que le endpoint répond
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	cfg, err := config.NewConfig()
	if err != nil {
		t.Skipf("Skipping test: cannot create config: %v", err)
		return
	}

	gin.SetMode(gin.TestMode)
	router := gin.New()
	apiRouter := api.NewAPIRouter(cfg.Database, cfg)
	apiRouter.Setup(router)

	req := httptest.NewRequest("GET", "/api/v1/status", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	// Le status peut être "ok" ou "degraded" selon l'état des services
	assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusServiceUnavailable)

	var response handlers.StatusResponse
	err = json.Unmarshal(w.Body.Bytes(), &response)
	assert.NoError(t, err)
	assert.Contains(t, []string{"ok", "degraded"}, response.Status)
}

// TestAPIHealthHTTP is a basic HTTP test
func TestAPIHealthHTTP(t *testing.T) {
	// This test requires the API server to be running
	// In CI, use docker-compose or a test server
	baseURL := "http://localhost:8080"
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	resp, err := http.Get(baseURL + "/api/v1/health")
	if err != nil {
		t.Skipf("API server not available: %v", err)
		return
	}
	defer resp.Body.Close()

	assert.Equal(t, http.StatusOK, resp.StatusCode)
}

// <<< VEZA:END api_health_test.go
