package app

import (
	"context"
	"testing"

	"google.golang.org/grpc/metadata"
)

func TestClientInfoFromContext(t *testing.T) {
	tests := []struct {
		name          string
		md            metadata.MD
		wantIP        string
		wantUserAgent string
	}{
		{
			name:          "нет метаданных",
			wantIP:        "",
			wantUserAgent: "",
		},
		{
			name: "x-forwarded-for через gateway: берём последний элемент",
			md: metadata.MD{
				"x-forwarded-for":        []string{"203.0.113.1, 198.51.100.7"},
				"grpcgateway-user-agent": []string{"Mozilla/5.0 (test)"},
			},
			wantIP:        "198.51.100.7",
			wantUserAgent: "Mozilla/5.0 (test)",
		},
		{
			name: "x-real-ip от доверенного прокси приоритетнее x-forwarded-for",
			md: metadata.MD{
				"x-real-ip":              []string{"192.0.2.10"},
				"x-forwarded-for":        []string{"203.0.113.1, 10.0.0.1"},
				"grpcgateway-user-agent": []string{"curl/8.0"},
			},
			wantIP:        "192.0.2.10",
			wantUserAgent: "curl/8.0",
		},
		{
			name: "x-real-ip пустой — фолбэк на x-forwarded-for",
			md: metadata.MD{
				"x-real-ip":       []string{" "},
				"x-forwarded-for": []string{"203.0.113.5"},
			},
			wantIP: "203.0.113.5",
		},
		{
			name: "user-agent для прямого gRPC-клиента",
			md: metadata.MD{
				"user-agent": []string{"grpc-go/1.60"},
			},
			wantUserAgent: "grpc-go/1.60",
		},
		{
			name: "x-forwarded-for с пробелами после запятых",
			md: metadata.MD{
				"x-forwarded-for": []string{"203.0.113.1 ,  198.51.100.7 "},
			},
			wantIP: "198.51.100.7",
		},
		{
			name: "невалидный x-real-ip — фолбэк на валидный x-forwarded-for",
			md: metadata.MD{
				"x-real-ip":       []string{"not-an-ip; drop me"},
				"x-forwarded-for": []string{"203.0.113.1, 198.51.100.7"},
			},
			wantIP: "198.51.100.7",
		},
		{
			name: "все источники невалидны — IP пустой (спуфинг)",
			md: metadata.MD{
				"x-real-ip":       []string{"not-an-ip; drop me"},
				"x-forwarded-for": []string{"256.256.256.256"},
			},
			wantIP: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var ctx context.Context = context.Background()
			if tt.md != nil {
				ctx = metadata.NewIncomingContext(ctx, tt.md)
			}
			ip, userAgent := clientInfoFromContext(ctx)
			if ip != tt.wantIP {
				t.Errorf("ip = %q, want %q", ip, tt.wantIP)
			}
			if userAgent != tt.wantUserAgent {
				t.Errorf("userAgent = %q, want %q", userAgent, tt.wantUserAgent)
			}
		})
	}
}
