package clients

import (
	"strings"
	"testing"
)

func TestOpenAIChatOfficialParametersSurviveBoundary(t *testing.T) {
	body := map[string]any{}
	for key := range openAIChatRequestParameters {
		body[key] = "sentinel-" + key
	}
	body["conversationId"] = "internal"
	body["unknown"] = "must-not-leak"

	filtered := FilterOpenAIChatRequestBody(body)
	for key := range openAIChatRequestParameters {
		if _, ok := filtered[key]; !ok {
			t.Fatalf("official Chat parameter %q was removed", key)
		}
	}
	for _, key := range []string{"conversationId", "unknown"} {
		if _, ok := filtered[key]; ok {
			t.Fatalf("internal/unknown parameter %q leaked upstream", key)
		}
	}
}

func TestOpenAIResponsesOfficialParametersSurviveBoundary(t *testing.T) {
	body := map[string]any{}
	for key := range openAIResponsesRequestParameters {
		body[key] = "sentinel-" + key
	}
	body["request_id"] = "internal"
	body["unknown"] = "must-not-leak"

	filtered := FilterOpenAIResponsesRequestBody(body)
	for key := range openAIResponsesRequestParameters {
		if _, ok := filtered[key]; !ok {
			t.Fatalf("official Responses parameter %q was removed", key)
		}
	}
	for _, key := range []string{"request_id", "unknown"} {
		if _, ok := filtered[key]; ok {
			t.Fatalf("internal/unknown parameter %q leaked upstream", key)
		}
	}
}

func TestValidateOpenAIRequestParametersRejectsUnknownTopLevelField(t *testing.T) {
	err := ValidateOpenAIRequestParameters("responses", map[string]any{"model": "demo", "input": "hello", "rogue": true})
	if err == nil || ErrorCode(err) != "invalid_parameter" || !strings.Contains(err.Error(), "rogue") {
		t.Fatalf("expected OpenAI-style invalid_parameter for rogue field, got %v", err)
	}
	if ErrorParam(err) != "rogue" {
		t.Fatalf("expected rogue parameter attribution, got %q", ErrorParam(err))
	}
	if err := ValidateOpenAIRequestParameters("responses", map[string]any{"model": "demo", "input": "hello", "messages": []any{}, "request_id": "internal"}); err != nil {
		t.Fatalf("expected controlled Responses extensions to remain accepted, got %v", err)
	}
}

func TestValidateOpenAIRequestParametersAcceptsInternalSimulationAndAffinityFields(t *testing.T) {
	body := map[string]any{
		"model": "demo", "messages": []any{}, "simulation": true,
		"simulationDurationMs": 5, "simulationUsage": map[string]any{"inputTokens": 10},
		"cacheAffinityKey": "conversation-1",
	}
	if err := ValidateOpenAIRequestParameters("chat.completions", body); err != nil {
		t.Fatalf("expected documented gateway extensions to remain accepted, got %v", err)
	}
	filtered := FilterOpenAIChatRequestBody(body)
	for _, key := range []string{"simulation", "simulationDurationMs", "simulationUsage", "cacheAffinityKey"} {
		if _, ok := filtered[key]; ok {
			t.Fatalf("gateway-only field %q leaked upstream", key)
		}
	}
}

func TestResponsesFallbackMapsEquivalentCurrentParameters(t *testing.T) {
	body, err := ResponsesRequestToChat(map[string]any{
		"input": "hello", "store": false, "metadata": map[string]any{"trace": "1"},
		"request_id": "internal-request", "platform_id": "internal-platform",
		"moderation": map[string]any{"type": "auto"}, "prompt_cache_key": "cache-key",
		"prompt_cache_options": map[string]any{"type": "ephemeral"}, "prompt_cache_retention": "in_memory",
		"safety_identifier": "safe", "service_tier": "priority", "top_logprobs": 3,
		"stream_options": map[string]any{"include_usage": true},
		"text":           map[string]any{"format": map[string]any{"type": "text"}, "verbosity": "low"},
	}, nil)
	if err != nil {
		t.Fatalf("convert Responses request: %v", err)
	}
	for _, key := range []string{"store", "metadata", "moderation", "prompt_cache_key", "prompt_cache_options", "prompt_cache_retention", "safety_identifier", "service_tier", "top_logprobs", "stream_options", "verbosity"} {
		if _, ok := body[key]; !ok {
			t.Fatalf("equivalent parameter %q was not mapped", key)
		}
	}
	if body["logprobs"] != true {
		t.Fatalf("top_logprobs fallback must enable Chat logprobs: %+v", body)
	}
	for _, key := range []string{"request_id", "platform_id"} {
		if _, ok := body[key]; ok {
			t.Fatalf("internal Responses parameter %q leaked into Chat fallback: %+v", key, body)
		}
	}
}
