package ai.sentryagent.idp.services;

import ai.sentryagent.idp.AgentIdPException;
import ai.sentryagent.idp.MockServer;
import ai.sentryagent.idp.internal.HttpHelper;
import ai.sentryagent.idp.models.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class AgentRegistryClientTest {

    private MockServer srv;
    private AgentRegistryClient client;

    private static final String AGENT_JSON = """
        {"agentId":"uuid-1","email":"a@b.ai","agentType":"screener","version":"1.0.0",
         "capabilities":["read"],"owner":"team","deploymentEnv":"production",
         "status":"active","createdAt":"2026-01-01T00:00:00Z","updatedAt":"2026-01-01T00:00:00Z"}
        """;

    private static final String PAGINATED_AGENTS = """
        {"data":[%s],"total":1,"page":1,"limit":20}
        """.formatted(AGENT_JSON.strip());

    @BeforeEach
    void setUp() throws IOException {
        srv = new MockServer();
        HttpClient httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
        HttpHelper httpHelper = new HttpHelper(httpClient);
        client = new AgentRegistryClient(srv.baseUrl(), () -> "test-token", httpHelper);
    }

    @AfterEach
    void tearDown() { srv.stop(); }

    @Test
    void registerAgent_returns201() {
        srv.addHandler("/api/v1/agents", 201, AGENT_JSON);
        Agent agent = client.registerAgent(RegisterAgentRequest.builder()
            .email("a@b.ai").agentType("screener").version("1.0.0")
            .capabilities(List.of("read")).owner("team").deploymentEnv("production")
            .build());
        assertEquals("uuid-1", agent.getAgentId());
        assertEquals("screener", agent.getAgentType());
    }

    @Test
    void listAgents_returnsPaginated() {
        srv.addHandler("/api/v1/agents", 200, PAGINATED_AGENTS);
        PaginatedAgents result = client.listAgents(null);
        assertEquals(1, result.getTotal());
        assertEquals("uuid-1", result.getData().get(0).getAgentId());
    }

    @Test
    void getAgent_returnsAgent() {
        srv.addHandler("/api/v1/agents/uuid-1", 200, AGENT_JSON);
        Agent agent = client.getAgent("uuid-1");
        assertEquals("uuid-1", agent.getAgentId());
    }

    @Test
    void getAgent_notFound_throwsAgentIdPException() {
        srv.addHandler("/api/v1/agents/bad-id", 404,
            "{\"code\":\"AgentNotFoundError\",\"message\":\"Not found.\"}");
        AgentIdPException ex = assertThrows(AgentIdPException.class, () -> client.getAgent("bad-id"));
        assertEquals("AgentNotFoundError", ex.getCode());
        assertEquals(404, ex.getHttpStatus());
    }

    @Test
    void updateAgent_returnsUpdated() {
        srv.addHandler("/api/v1/agents/uuid-1", 200, AGENT_JSON);
        Agent agent = client.updateAgent("uuid-1",
            UpdateAgentRequest.builder().version("2.0.0").build());
        assertNotNull(agent);
        assertEquals("uuid-1", agent.getAgentId());
    }

    @Test
    void decommissionAgent_returns204() {
        srv.addHandler("/api/v1/agents/uuid-1", 204, null);
        assertDoesNotThrow(() -> client.decommissionAgent("uuid-1"));
    }

    @Test
    void registerAgentAsync_returnsCompletableFuture() throws Exception {
        srv.addHandler("/api/v1/agents", 201, AGENT_JSON);
        Agent agent = client.registerAgentAsync(RegisterAgentRequest.builder()
            .email("a@b.ai").agentType("screener").version("1.0.0")
            .capabilities(List.of("read")).owner("team").deploymentEnv("production")
            .build()).get();
        assertEquals("uuid-1", agent.getAgentId());
    }

    @Test
    void getAgentAsync_returnsCompletableFuture() throws Exception {
        srv.addHandler("/api/v1/agents/uuid-1", 200, AGENT_JSON);
        Agent agent = client.getAgentAsync("uuid-1").get();
        assertEquals("uuid-1", agent.getAgentId());
    }

    @Test
    void listAgentsAsync_withParams() throws Exception {
        srv.addHandler("/api/v1/agents", 200, PAGINATED_AGENTS);
        PaginatedAgents result = client.listAgentsAsync(
            ListAgentsParams.builder().status("active").page(1).limit(20).build()
        ).get();
        assertEquals(1, result.getTotal());
    }

    @Test
    void decommissionAgentAsync_completesSuccessfully() throws Exception {
        srv.addHandler("/api/v1/agents/uuid-1", 204, null);
        assertDoesNotThrow(() -> client.decommissionAgentAsync("uuid-1").get());
    }

    @Test
    void updateAgentAsync_returnsCompletableFuture() throws Exception {
        srv.addHandler("/api/v1/agents/uuid-1", 200, AGENT_JSON);
        Agent agent = client.updateAgentAsync("uuid-1",
            UpdateAgentRequest.builder().version("2.0.0").build()).get();
        assertEquals("uuid-1", agent.getAgentId());
    }
}
