package clients

// Keep these lists aligned with openai-node 6.47.0 and the public OpenAI API
// reference. They document and test the currently known surface, but are not an
// upstream allowlist: unknown fields may be introduced by OpenAI after a
// Gateway release and must remain transparent.
var openAIChatRequestParameters = stringSet(
	"messages", "model", "audio", "frequency_penalty", "function_call", "functions",
	"logit_bias", "logprobs", "max_completion_tokens", "max_tokens", "metadata",
	"modalities", "moderation", "n", "parallel_tool_calls", "prediction",
	"presence_penalty", "prompt_cache_key", "prompt_cache_options", "prompt_cache_retention",
	"reasoning_effort", "response_format", "safety_identifier", "seed", "service_tier",
	"stop", "store", "stream", "stream_options", "temperature", "tool_choice", "tools",
	"top_logprobs", "top_p", "user", "verbosity", "web_search_options",
)

var openAIResponsesRequestParameters = stringSet(
	"background", "context_management", "conversation", "include", "input", "instructions",
	"max_output_tokens", "max_tool_calls", "metadata", "model", "moderation",
	"parallel_tool_calls", "previous_response_id", "prompt", "prompt_cache_key",
	"prompt_cache_options", "prompt_cache_retention", "reasoning", "safety_identifier",
	"service_tier", "store", "stream", "stream_options", "temperature", "text",
	"tool_choice", "tools", "top_logprobs", "top_p", "truncation", "user",
)

var gatewayOpenAIRequestExtensions = stringSet(
	"runMode", "run_mode", "conversationId", "conversation_id", "sessionId", "session_id",
	"requestId", "request_id", "signal", "userMessage", "user_message", "platformId",
	"platform_id", "options", "enable_thinking", "thinking_budget", "thinking_budget_tokens", "enable_web_search",
	"modelType", "model_type", "capability", "capabilityType", "mode", "simulation", "testMode",
	"cacheAffinityKey", "cache_affinity_key", "simulationDurationMs", "simulationDurationSeconds",
	"simulationMinDurationMs", "simulationMaxDurationMs", "simulationMinDurationSeconds",
	"simulationMaxDurationSeconds", "simulationDurationMinMs", "simulationDurationMaxMs",
	"simulationDurationMinSeconds", "simulationDurationMaxSeconds", "simulationFailure",
	"simulationProfile", "simulationUsage",
)

var gatewayResponsesRequestExtensions = stringSet("messages", "presence_penalty", "frequency_penalty")

var controlledOpenAIChatProviderParameters = stringSet(
	"enable_thinking", "thinking_budget", "thinking", "enable_web_search",
)

var controlledOpenAIResponsesProviderParameters = stringSet("presence_penalty", "frequency_penalty")

func ValidateOpenAIRequestParameters(kind string, body map[string]any) error {
	// OpenAI-compatible public endpoints intentionally accept future official
	// fields. Provider validation remains authoritative for fields the selected
	// upstream does not support.
	_ = kind
	_ = body
	return nil
}

func FilterOpenAIChatRequestBody(body map[string]any) map[string]any {
	return filterOpenAIRequestBody(body, controlledOpenAIChatProviderParameters, nil)
}

func FilterOpenAIResponsesRequestBody(body map[string]any) map[string]any {
	return filterOpenAIRequestBody(body, controlledOpenAIResponsesProviderParameters, gatewayResponsesRequestExtensions)
}

func filterOpenAIRequestBody(body map[string]any, controlled map[string]struct{}, protocolInternal map[string]struct{}) map[string]any {
	out := make(map[string]any, len(body))
	for key, value := range body {
		if _, ok := controlled[key]; ok {
			out[key] = value
			continue
		}
		if _, internal := gatewayOpenAIRequestExtensions[key]; internal {
			continue
		}
		if _, internal := protocolInternal[key]; internal {
			continue
		}
		out[key] = value
	}
	return out
}

func stringSet(values ...string) map[string]struct{} {
	out := make(map[string]struct{}, len(values))
	for _, value := range values {
		out[value] = struct{}{}
	}
	return out
}
