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 static org.junit.jupiter.api.Assertions.*;

class AuditClientTest {

    private MockServer srv;
    private AuditClient client;

    private static final String AUDIT_EVENT = """
        {"eventId":"ev-1","agentId":"uuid-1","action":"token.issued","outcome":"success",
         "ipAddress":"1.2.3.4","userAgent":"curl","metadata":{},"timestamp":"2026-01-01T00:00:00Z"}
        """;

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

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

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

    @Test
    void queryAuditLog_returnsPaginated() {
        srv.addHandler("/api/v1/audit", 200, PAGINATED_AUDIT);
        PaginatedAuditEvents result = client.queryAuditLog(null);
        assertEquals(1, result.getTotal());
        assertEquals("ev-1", result.getData().get(0).getEventId());
    }

    @Test
    void queryAuditLog_withParams() {
        srv.addHandler("/api/v1/audit", 200, PAGINATED_AUDIT);
        PaginatedAuditEvents result = client.queryAuditLog(
            QueryAuditParams.builder()
                .agentId("uuid-1")
                .action("token.issued")
                .fromDate("2026-01-01")
                .build());
        assertEquals(1, result.getTotal());
    }

    @Test
    void getAuditEvent_returnsEvent() {
        srv.addHandler("/api/v1/audit/ev-1", 200, AUDIT_EVENT);
        AuditEvent event = client.getAuditEvent("ev-1");
        assertEquals("ev-1", event.getEventId());
        assertEquals("token.issued", event.getAction());
        assertEquals("success", event.getOutcome());
    }

    @Test
    void getAuditEvent_notFound_throwsAgentIdPException() {
        srv.addHandler("/api/v1/audit/bad-id", 404,
            "{\"code\":\"AuditEventNotFoundError\",\"message\":\"Event not found.\"}");
        AgentIdPException ex = assertThrows(AgentIdPException.class,
            () -> client.getAuditEvent("bad-id"));
        assertEquals("AuditEventNotFoundError", ex.getCode());
        assertEquals(404, ex.getHttpStatus());
    }

    @Test
    void queryAuditLogAsync_returnsPaginated() throws Exception {
        srv.addHandler("/api/v1/audit", 200, PAGINATED_AUDIT);
        PaginatedAuditEvents result = client.queryAuditLogAsync(null).get();
        assertEquals(1, result.getTotal());
    }

    @Test
    void getAuditEventAsync_returnsEvent() throws Exception {
        srv.addHandler("/api/v1/audit/ev-1", 200, AUDIT_EVENT);
        AuditEvent event = client.getAuditEventAsync("ev-1").get();
        assertEquals("ev-1", event.getEventId());
    }
}
