package com.easyagents.embedding.openai;

import com.easyagents.core.document.Document;
import com.easyagents.core.model.client.HttpClient;
import com.easyagents.core.model.embedding.EmbeddingOptions;
import com.easyagents.core.model.exception.ModelException;
import org.junit.Assert;
import org.junit.Test;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Tests for OpenAI-compatible embeddings request payload generation.
 */
public class OpenAIEmbeddingModelTest {

    /**
     * Verifies that fixed-dimension embeddings models do not receive dimensions.
     */
    @Test
    public void shouldNotSendDimensionsForBgeModel() {
        OpenAIEmbeddingConfig config = new OpenAIEmbeddingConfig();
        config.setModel("BAAI/bge-m3");
        EmbeddingOptions options = new EmbeddingOptions();
        options.setDimensions(1024);

        String payload = OpenAIEmbeddingModel.promptToEmbeddingsPayload(Document.of("hello"), options, config);

        Assert.assertFalse(payload.contains("\"dimensions\""));
    }

    /**
     * Verifies that Qwen3 embedding models keep the dynamic dimensions parameter.
     */
    @Test
    public void shouldSendDimensionsForQwen3EmbeddingModel() {
        OpenAIEmbeddingConfig config = new OpenAIEmbeddingConfig();
        config.setModel("Qwen/Qwen3-Embedding-8B");
        EmbeddingOptions options = new EmbeddingOptions();
        options.setDimensions(1024);

        String payload = OpenAIEmbeddingModel.promptToEmbeddingsPayload(Document.of("hello"), options, config);

        Assert.assertTrue(payload.contains("\"dimensions\":1024"));
    }

    /**
     * Verifies that malformed embeddings responses fail with a clear model exception.
     */
    @Test
    public void shouldThrowModelExceptionWhenEmbeddingMissing() {
        OpenAIEmbeddingConfig config = new OpenAIEmbeddingConfig();
        config.setProvider("test-provider");
        config.setModel("BAAI/bge-m3");
        config.setApiKey("test-key");
        OpenAIEmbeddingModel model = new OpenAIEmbeddingModel(config);
        model.setHttpClient(new HttpClient() {
            @Override
            public String post(String url, Map<String, String> headers, String payload) {
                return "{\"data\":[{}]}";
            }
        });

        ModelException exception = Assert.assertThrows(
            ModelException.class,
            () -> model.embed(Document.of("hello"))
        );

        Assert.assertTrue(exception.getMessage().contains("data[0].embedding"));
    }

    /**
     * Verifies that invalid JSON responses are reported as embedding response parsing failures.
     */
    @Test
    public void shouldThrowModelExceptionWhenResponseIsInvalidJson() {
        OpenAIEmbeddingConfig config = new OpenAIEmbeddingConfig();
        config.setProvider("test-provider");
        config.setModel("BAAI/bge-m3");
        config.setApiKey("test-key");
        OpenAIEmbeddingModel model = new OpenAIEmbeddingModel(config);
        model.setHttpClient(new HttpClient() {
            @Override
            public String post(String url, Map<String, String> headers, String payload) {
                return "not-json";
            }
        });

        ModelException exception = Assert.assertThrows(
            ModelException.class,
            () -> model.embed(Document.of("hello"))
        );

        Assert.assertEquals("Failed to parse embedding response.", exception.getMessage());
        Assert.assertNotNull(exception.getCause());
    }

    /**
     * Verifies that diagnostic headers retain ordinary values without exposing credentials.
     */
    @Test
    public void shouldRedactAuthorizationHeaderForFailureLogging() {
        Map<String, String> headers = new LinkedHashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", "Bearer test-key");

        Map<String, String> sanitizedHeaders = OpenAIEmbeddingModel.sanitizeHeadersForLogging(headers);

        Assert.assertEquals("application/json", sanitizedHeaders.get("Content-Type"));
        Assert.assertEquals("[REDACTED]", sanitizedHeaders.get("Authorization"));
        Assert.assertEquals("Bearer test-key", headers.get("Authorization"));
    }
}
