package com.cloudhandson.vpdbackoffice.service;

import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.jupiter.api.Test;

class McpSseServiceTest {

  private final ObjectMapper objectMapper = new ObjectMapper();
  private final SelectAiAgentOrdsService selectAiAgentOrdsService = new CapturingSelectAiAgentOrdsService();
  private final McpSseService service = new McpSseService(
      selectAiAgentOrdsService,
      objectMapper
  );

  @Test
  void listsOnlyVpdSelectAiToolWithPromptInput() {
    ObjectNode response = service.handle("default", request(1, "tools/list"));

    var tools = response.path("result").path("tools");
    assertThat(tools).hasSize(1);
    var selectAi = tools.get(0);
    assertThat(selectAi.path("name").asText()).isEqualTo("ords.query.kb_select_ai_vpd");
    assertThat(selectAi.path("inputSchema").path("required"))
        .extracting(node -> node.asText())
        .contains("prompt");
    assertThat(selectAi.path("inputSchema").path("properties").has("bearerToken")).isFalse();
    assertThat(selectAi.path("inputSchema").path("properties").has("limit")).isTrue();
    assertThat(selectAi.path("inputSchema").path("properties").has("conversationId")).isFalse();
  }

  @Test
  void callsVpdSelectAiThroughOrdsService() {
    ObjectNode request = request(2, "tools/call");
    ObjectNode params = (ObjectNode) request.putObject("params");
    params.put("name", "ords.query.kb_select_ai_vpd");
    ObjectNode arguments = params.putObject("arguments");
    arguments.put("prompt", "고객 수를 조회해 줘");
    arguments.put("limit", 25);

    ObjectNode response = service.handle("default", request, "user-bearer");

    CapturingSelectAiAgentOrdsService agentService =
        (CapturingSelectAiAgentOrdsService) selectAiAgentOrdsService;
    assertThat(agentService.bearerToken).isEqualTo("user-bearer");
    assertThat(agentService.prompt).isEqualTo("고객 수를 조회해 줘");
    assertThat(agentService.limit).isEqualTo(25);
    assertThat(response.path("error").isMissingNode()).isTrue();
    assertThat(response.path("result").path("isError").asBoolean()).isFalse();
    assertThat(response.path("result").path("content").get(0).path("text").asText())
        .contains("KB_AIDP_SELECTAI_GPT54_MINI_FULLMETA_PROFILE_V1")
        .contains("SELECT COUNT(*) FROM KB_CUSTOMERS");
  }

  @Test
  void returnsToolLevelDeniedResultWhenVpdTokenIsMissing() {
    ObjectNode request = request(3, "tools/call");
    ObjectNode params = (ObjectNode) request.putObject("params");
    params.put("name", "ords.query.kb_select_ai_vpd");
    params.putObject("arguments").put("prompt", "고객 수를 조회해 줘");

    ObjectNode response = service.handle("default", request, "");

    assertThat(response.path("error").isMissingNode()).isTrue();
    assertThat(response.path("result").path("isError").asBoolean()).isTrue();
    assertThat(response.path("result").path("content").get(0).path("text").asText())
        .contains("VPD_TOKEN_DENIED")
        .contains("권한이 없습니다");
  }

  private ObjectNode request(int id, String method) {
    ObjectNode request = objectMapper.createObjectNode();
    request.put("jsonrpc", "2.0");
    request.put("id", id);
    request.put("method", method);
    return request;
  }

  private static final class CapturingSelectAiAgentOrdsService extends SelectAiAgentOrdsService {

    private String bearerToken;
    private String prompt;
    private int limit;

    private CapturingSelectAiAgentOrdsService() {
      super(null, null, new ObjectMapper());
    }

    @Override
    public JsonNode run(String bearerToken, String prompt, int limit) {
      this.bearerToken = bearerToken;
      this.prompt = prompt;
      this.limit = limit;
      return new ObjectMapper().createObjectNode()
          .put("profile", "KB_AIDP_SELECTAI_GPT54_MINI_FULLMETA_PROFILE_V1")
          .put("generatedSql", "SELECT COUNT(*) FROM KB_CUSTOMERS");
    }
  }
}
