package com.cameleer.server.app.security;

import com.cameleer.server.app.AbstractPostgresIT;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
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.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

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

/**
 * Integration tests verifying bootstrap token validation on the registration endpoint.
 */
class BootstrapTokenIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private static final String REGISTRATION_JSON = """
            {
              "instanceId": "bootstrap-test-agent",
              "applicationId": "test-group",
              "environmentId": "default",
              "version": "1.0.0",
              "routeIds": [],
              "capabilities": {}
            }
            """;

    @Test
    void registerWithoutBootstrapToken_returns401() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Cameleer-Protocol-Version", "1");

        ResponseEntity<String> response = restTemplate.postForEntity(
                "/api/v1/agents/register",
                new HttpEntity<>(REGISTRATION_JSON, headers),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
    }

    @Test
    void registerWithWrongBootstrapToken_returns401() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Cameleer-Protocol-Version", "1");
        headers.set("Authorization", "Bearer wrong-token-value");

        ResponseEntity<String> response = restTemplate.postForEntity(
                "/api/v1/agents/register",
                new HttpEntity<>(REGISTRATION_JSON, headers),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
    }

    @Test
    void registerWithCorrectBootstrapToken_returns200WithTokens() throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Cameleer-Protocol-Version", "1");
        headers.set("Authorization", "Bearer test-bootstrap-token");

        ResponseEntity<String> response = restTemplate.postForEntity(
                "/api/v1/agents/register",
                new HttpEntity<>(REGISTRATION_JSON, headers),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

        JsonNode body = objectMapper.readTree(response.getBody());
        assertThat(body.get("accessToken").asText()).isNotEmpty();
        assertThat(body.get("refreshToken").asText()).isNotEmpty();
        assertThat(body.get("serverPublicKey").asText()).isNotEmpty();
    }

    @Test
    void registerWithPreviousBootstrapToken_returns200() {
        // Dual-token rotation: previous token should also be accepted
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Cameleer-Protocol-Version", "1");
        headers.set("Authorization", "Bearer old-bootstrap-token");

        String json = """
                {
                  "instanceId": "bootstrap-test-previous",
                  "applicationId": "test-group",
                  "environmentId": "default",
                  "version": "1.0.0",
                  "routeIds": [],
                  "capabilities": {}
                }
                """;

        ResponseEntity<String> response = restTemplate.postForEntity(
                "/api/v1/agents/register",
                new HttpEntity<>(json, headers),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    }
}
