package middleware

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

// ============================================================================
// TestCORSMiddleware - Tests for CORS middleware
// ============================================================================

func TestCORSMiddleware_AllowedOrigin(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_AllowedOrigin ===")

	// Set allowed origins
	os.Setenv("CORS_ORIGINS", "http://localhost:3000,http://example.com")
	defer os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("[TEST LOG] Handler reached - CORS headers should be set")
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("GET", "/api/test", nil)
	req.Header.Set("Origin", "http://localhost:3000")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s'\n", rr.Header().Get("Access-Control-Allow-Origin"))
	fmt.Printf("[TEST LOG] Access-Control-Allow-Credentials: '%s'\n", rr.Header().Get("Access-Control-Allow-Credentials"))

	assert.Equal(t, "http://localhost:3000", rr.Header().Get("Access-Control-Allow-Origin"))
	assert.Equal(t, "true", rr.Header().Get("Access-Control-Allow-Credentials"))
	assert.Equal(t, http.StatusOK, rr.Code)
}

func TestCORSMiddleware_DeniedOrigin(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_DeniedOrigin ===")

	os.Setenv("CORS_ORIGINS", "http://localhost:3000")
	defer os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("[TEST LOG] Handler reached - CORS origin should be empty")
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("GET", "/api/test", nil)
	req.Header.Set("Origin", "http://evil.com")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s' (expected empty)\n", rr.Header().Get("Access-Control-Allow-Origin"))

	// Origin not in allowed list - should not set Access-Control-Allow-Origin
	assert.Equal(t, "", rr.Header().Get("Access-Control-Allow-Origin"))
	// But credentials header should still be set
	assert.Equal(t, "true", rr.Header().Get("Access-Control-Allow-Credentials"))
	assert.Equal(t, http.StatusOK, rr.Code)
}

func TestCORSMiddleware_WildcardOrigin(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_WildcardOrigin ===")

	os.Setenv("CORS_ORIGINS", "*")
	defer os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("[TEST LOG] Handler reached - wildcard CORS")
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("GET", "/api/test", nil)
	req.Header.Set("Origin", "http://any-origin.com")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s' (expected *)\n", rr.Header().Get("Access-Control-Allow-Origin"))

	assert.Equal(t, "*", rr.Header().Get("Access-Control-Allow-Origin"))
	assert.Equal(t, http.StatusOK, rr.Code)
}

func TestCORSMiddleware_PreflightOptions(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_PreflightOptions ===")

	os.Setenv("CORS_ORIGINS", "http://localhost:3000")
	defer os.Unsetenv("CORS_ORIGINS")

	handlerCalled := false
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		handlerCalled = true
		t.Error("Handler should not be called for OPTIONS preflight")
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("OPTIONS", "/api/test", nil)
	req.Header.Set("Origin", "http://localhost:3000")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Response status: %d (expected: 200 for preflight)\n", rr.Code)
	fmt.Printf("[TEST LOG] Handler was called: %v (expected: false)\n", handlerCalled)
	fmt.Printf("[TEST LOG] Access-Control-Allow-Methods: '%s'\n", rr.Header().Get("Access-Control-Allow-Methods"))

	assert.False(t, handlerCalled)
	assert.Equal(t, http.StatusOK, rr.Code)
	assert.Contains(t, rr.Header().Get("Access-Control-Allow-Methods"), "POST")
	assert.Contains(t, rr.Header().Get("Access-Control-Allow-Methods"), "GET")
	assert.Contains(t, rr.Header().Get("Access-Control-Allow-Methods"), "PUT")
	assert.Contains(t, rr.Header().Get("Access-Control-Allow-Methods"), "DELETE")
	assert.Contains(t, rr.Header().Get("Access-Control-Allow-Headers"), "Authorization")
}

func TestCORSMiddleware_DefaultOrigin(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_DefaultOrigin ===")

	// Clear CORS_ORIGINS to test default
	os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("[TEST LOG] Handler reached - default origin")
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("GET", "/api/test", nil)
	req.Header.Set("Origin", "http://localhost:3000")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s'\n", rr.Header().Get("Access-Control-Allow-Origin"))

	// Default should allow localhost:3000
	assert.Equal(t, "http://localhost:3000", rr.Header().Get("Access-Control-Allow-Origin"))
	assert.Equal(t, http.StatusOK, rr.Code)
}

func TestCORSMiddleware_MultipleOrigins(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_MultipleOrigins ===")

	os.Setenv("CORS_ORIGINS", "http://app.example.com, http://admin.example.com")
	defer os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	// Test second origin in list
	req := httptest.NewRequest("GET", "/api/test", nil)
	req.Header.Set("Origin", "http://admin.example.com")
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s'\n", rr.Header().Get("Access-Control-Allow-Origin"))

	assert.Equal(t, "http://admin.example.com", rr.Header().Get("Access-Control-Allow-Origin"))
}

func TestCORSMiddleware_NoOriginHeader(t *testing.T) {
	fmt.Println("\n[TEST] === TestCORSMiddleware_NoOriginHeader ===")

	os.Setenv("CORS_ORIGINS", "http://localhost:3000")
	defer os.Unsetenv("CORS_ORIGINS")

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("[TEST LOG] Handler reached - no origin header in request")
		w.WriteHeader(http.StatusOK)
	})

	middleware := CORSMiddleware(handler)

	req := httptest.NewRequest("GET", "/api/test", nil)
	// No Origin header set
	rr := httptest.NewRecorder()

	middleware.ServeHTTP(rr, req)

	fmt.Printf("[TEST LOG] Access-Control-Allow-Origin: '%s' (expected empty)\n", rr.Header().Get("Access-Control-Allow-Origin"))

	// No origin means no matching, so header should be empty
	assert.Equal(t, "", rr.Header().Get("Access-Control-Allow-Origin"))
	assert.Equal(t, http.StatusOK, rr.Code)
}
