package com.cloudhandson.vpdbackoffice.service;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.JdbcTemplate;

class McpAgentToolStartupValidatorTest {

  private final McpToolCatalog toolCatalog = mock(McpToolCatalog.class);
  private final JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
  private final McpAgentToolStartupValidator validator =
      new McpAgentToolStartupValidator(toolCatalog, jdbcTemplate);

  @Test
  void acceptsEnabledAgentToolsAndChecksDuplicateTargetOnce() {
    when(toolCatalog.tools()).thenReturn(List.of(
        agentTool("resolve_hr_term", "HMM_HR_TERM_RESOLVER"),
        agentTool("resolve_hr_alias", "HMM_HR_TERM_RESOLVER"),
        agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
    ));
    when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
        .thenReturn(List.of(
            Map.of("TOOL_NAME", "HMM_HR_TERM_RESOLVER", "STATUS", "ENABLED"),
            Map.of("TOOL_NAME", "HMM_HR_POLICY_SEARCH", "STATUS", "enabled")
        ));

    validator.validateAdvertisedAgentTools();

    verify(jdbcTemplate).queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL);
  }

  @Test
  void rejectsMissingAgentTool() {
    when(toolCatalog.tools()).thenReturn(List.of(
        agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
    ));
    when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
        .thenReturn(List.of());

    assertThatThrownBy(validator::validateAdvertisedAgentTools)
        .isInstanceOf(IllegalStateException.class)
        .hasMessageContaining("missing=[HMM_HR_POLICY_SEARCH]");
  }

  @Test
  void rejectsDisabledAgentTool() {
    when(toolCatalog.tools()).thenReturn(List.of(
        agentTool("resolve_hr_term", "HMM_HR_TERM_RESOLVER")
    ));
    when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
        .thenReturn(List.of(
            Map.of("tool_name", "hmm_hr_term_resolver", "status", "DISABLED")
        ));

    assertThatThrownBy(validator::validateAdvertisedAgentTools)
        .isInstanceOf(IllegalStateException.class)
        .hasMessageContaining("notEnabled=[HMM_HR_TERM_RESOLVER=DISABLED]");
  }

  @Test
  void skipsDatabaseLookupForApplicationNativeTools() {
    when(toolCatalog.tools()).thenReturn(List.of(selectAiTool("search_hr_data")));

    validator.validateAdvertisedAgentTools();

    verify(jdbcTemplate, never())
        .queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL);
  }

  @Test
  void rejectsMetadataLookupFailure() {
    when(toolCatalog.tools()).thenReturn(List.of(
        agentTool("search_hr_policy", "HMM_HR_POLICY_SEARCH")
    ));
    when(jdbcTemplate.queryForList(McpAgentToolStartupValidator.TOOL_METADATA_SQL))
        .thenThrow(new DataAccessResourceFailureException("metadata unavailable"));

    assertThatThrownBy(validator::validateAdvertisedAgentTools)
        .isInstanceOf(IllegalStateException.class)
        .hasMessageContaining("USER_AI_AGENT_TOOLS")
        .hasCauseInstanceOf(DataAccessResourceFailureException.class);
  }

  private McpToolDefinition agentTool(String publicName, String targetName) {
    return new McpToolDefinition(
        publicName,
        publicName,
        "description",
        "query",
        "query description",
        "AGENT_TOOL",
        targetName,
        "P_QUERY"
    );
  }

  private McpToolDefinition selectAiTool(String publicName) {
    return new McpToolDefinition(
        publicName,
        publicName,
        "description",
        "query",
        "query description",
        "SELECT_AI",
        "",
        ""
    );
  }
}
