package handlers

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

	"github.com/gin-gonic/gin"
)

func TestGetClientIPHeadersAndRemoteAddr(t *testing.T) {
	// Cloudflare header should win
	req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req.Header.Set("CF-Connecting-IP", "5.6.7.8")
	ip := getClientIP(req)
	if ip != "5.6.7.8" {
		t.Fatalf("expected 5.6.7.8 got %s", ip)
	}

	// X-Real-IP should be preferred over RemoteAddr
	req2 := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req2.Header.Set("X-Real-IP", "10.0.0.4")
	req2.RemoteAddr = "1.2.3.4:5678"
	ip2 := getClientIP(req2)
	if ip2 != "10.0.0.4" {
		t.Fatalf("expected 10.0.0.4 got %s", ip2)
	}

	// X-Forwarded-For returns first in list
	req3 := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req3.Header.Set("X-Forwarded-For", "192.168.0.1, 192.168.0.2")
	ip3 := getClientIP(req3)
	if ip3 != "192.168.0.1" {
		t.Fatalf("expected 192.168.0.1 got %s", ip3)
	}

	// Fallback to remote addr port trimmed
	req4 := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
	req4.RemoteAddr = "7.7.7.7:8888"
	ip4 := getClientIP(req4)
	if ip4 != "7.7.7.7" {
		t.Fatalf("expected 7.7.7.7 got %s", ip4)
	}
}

func TestGetMyIPHandler(t *testing.T) {
	gin.SetMode(gin.TestMode)
	r := gin.New()
	handler := NewSystemHandler()
	r.GET("/myip", handler.GetMyIP)

	t.Run("with CF header", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodGet, "/myip", http.NoBody)
		req.Header.Set("CF-Connecting-IP", "5.6.7.8")
		r.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("expected 200 got %d", w.Code)
		}
	})

	t.Run("with X-Forwarded-For header", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodGet, "/myip", http.NoBody)
		req.Header.Set("X-Forwarded-For", "9.9.9.9")
		r.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("expected 200 got %d", w.Code)
		}
	})

	t.Run("with X-Real-IP header", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodGet, "/myip", http.NoBody)
		req.Header.Set("X-Real-IP", "8.8.8.8")
		r.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("expected 200 got %d", w.Code)
		}
	})

	t.Run("direct connection", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodGet, "/myip", http.NoBody)
		req.RemoteAddr = "7.7.7.7:9999"
		r.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("expected 200 got %d", w.Code)
		}
	})
}
