package com.ruoyi.web.kb;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

import com.ruoyi.web.kb.service.impl.KbOpenAiProxyServiceImpl;
import com.ruoyi.web.kb.support.KbApiProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.exception.ServiceException;

@DisplayName("知识库包 OpenAI 转发 Service")
class KbOpenAiProxyServiceImplTest
{
    private KbApiProperties properties;

    private MockRestServiceServer mockServer;

    private KbOpenAiProxyServiceImpl service;

    @BeforeEach
    void setUp()
    {
        properties = new KbApiProperties();
        properties.setEnabled(true);
        properties.setScheme("http");
        properties.setHost("mock-llm");
        properties.setPort(9107);
        properties.setApiKey("yak_test_key");
        RestTemplate restTemplate = new RestTemplate();
        mockServer = MockRestServiceServer.createServer(restTemplate);
        service = new KbOpenAiProxyServiceImpl(properties, restTemplate, new ObjectMapper());
    }

    @Test
    @DisplayName("GET /v1/models 转发并带 Bearer")
    void listModelsForwardsAuth() throws Exception
    {
        mockServer.expect(requestTo("http://mock-llm:9107/v1/models"))
                .andExpect(method(HttpMethod.GET))
                .andExpect(header("Authorization", "Bearer yak_test_key"))
                .andRespond(withSuccess("{\"data\":[]}", MediaType.APPLICATION_JSON));
        ResponseEntity<byte[]> resp = service.listModels();
        assertEquals(200, resp.getStatusCodeValue());
        mockServer.verify();
    }

    @Test
    @DisplayName("POST /v1/chat/completions 非流式转发")
    void chatCompletionsForwardsBody() throws Exception
    {
        mockServer.expect(requestTo("http://mock-llm:9107/v1/chat/completions"))
                .andExpect(method(HttpMethod.POST))
                .andExpect(header("Authorization", "Bearer yak_test_key"))
                .andRespond(withSuccess("{\"id\":\"x\"}", MediaType.APPLICATION_JSON));
        ResponseEntity<byte[]> resp = service.chatCompletions("{\"model\":\"auto\",\"stream\":false}".getBytes());
        assertEquals(200, resp.getStatusCodeValue());
        mockServer.verify();
    }

    @Test
    @DisplayName("识别 stream=true")
    void detectsStreamRequest()
    {
        assertTrue(service.isStreamRequest("{\"stream\":true}".getBytes()));
        assertFalse(service.isStreamRequest("{\"stream\":false}".getBytes()));
    }

    @Test
    @DisplayName("未配置 api-key 时拒绝")
    void rejectsWithoutApiKey()
    {
        properties.setApiKey("");
        assertThrows(ServiceException.class, () -> service.listModels());
    }
}
