package com.cameleer.server.app.interceptor;

import com.cameleer.server.app.AbstractPostgresIT;
import com.cameleer.server.app.TestSecurityHelper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Integration tests for the protocol version interceptor.
 * With security enabled, requests to protected endpoints need JWT auth
 * to reach the interceptor layer.
 */
class ProtocolVersionIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private TestSecurityHelper securityHelper;

    private String jwt;

    @BeforeEach
    void setUp() {
        // Lift max_agents cap so this IT (which registers an agent) isn't gated by license
        // enforcement. Cap behaviour itself is exercised by AgentCapEnforcementIT.
        securityHelper.installSyntheticUnsignedLicense(Map.of("max_agents", 100));
        jwt = securityHelper.registerTestAgent("test-agent-protocol-it");
    }

    @AfterEach
    void tearDown() {
        securityHelper.clearTestLicense();
    }

    @Test
    void requestWithoutProtocolHeaderReturns400() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + jwt);
        var entity = new HttpEntity<>("{}", headers);

        var response = restTemplate.exchange(
                "/api/v1/data/executions", HttpMethod.POST, entity, String.class);
        assertThat(response.getStatusCode().value()).isEqualTo(400);
        assertThat(response.getBody()).contains("Missing or unsupported X-Cameleer-Protocol-Version header");
    }

    @Test
    void requestWithWrongProtocolVersionReturns400() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + jwt);
        headers.set("X-Cameleer-Protocol-Version", "2");
        var entity = new HttpEntity<>("{}", headers);

        var response = restTemplate.exchange(
                "/api/v1/data/executions", HttpMethod.POST, entity, String.class);
        assertThat(response.getStatusCode().value()).isEqualTo(400);
    }

    @Test
    void requestWithCorrectProtocolVersionPassesInterceptor() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + jwt);
        headers.set("X-Cameleer-Protocol-Version", "1");
        // Minimal valid ExecutionChunk envelope so the controller can accept
        // it; the prior {} body was treated by the chunk pipeline as an empty
        // envelope and rejected with 400, which made the interceptor-passed
        // signal ambiguous.
        String chunk = """
                {
                  "exchangeId": "protocol-version-1",
                  "applicationId": "test-group",
                  "instanceId": "test-agent-protocol-it",
                  "routeId": "protocol-version-route",
                  "status": "COMPLETED",
                  "startTime": "2026-03-11T10:00:00Z",
                  "endTime": "2026-03-11T10:00:01Z",
                  "durationMs": 1,
                  "chunkSeq": 0,
                  "final": true,
                  "processors": []
                }
                """;
        var entity = new HttpEntity<>(chunk, headers);

        var response = restTemplate.exchange(
                "/api/v1/data/executions", HttpMethod.POST, entity, String.class);
        assertThat(response.getStatusCode().value()).isNotEqualTo(400);
    }

    @Test
    void healthEndpointExcludedFromInterceptor() {
        var response = restTemplate.getForEntity("/api/v1/health", String.class);
        assertThat(response.getStatusCode().value()).isEqualTo(200);
    }

    @Test
    void apiDocsExcludedFromInterceptor() {
        var response = restTemplate.getForEntity("/api/v1/api-docs", String.class);
        assertThat(response.getStatusCode().value()).isEqualTo(200);
    }
}
