package com.cameleer.server.app.controller;

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

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

class SensitiveKeysAdminControllerIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private TestSecurityHelper securityHelper;

    private String adminJwt;
    private String viewerJwt;

    @BeforeEach
    void setUp() {
        adminJwt = securityHelper.adminToken();
        viewerJwt = securityHelper.viewerToken();
        jdbcTemplate.update("DELETE FROM server_config WHERE config_key = 'sensitive_keys'");
    }

    @Test
    void get_notConfigured_returns204() {
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.GET,
                new HttpEntity<>(securityHelper.authHeadersNoBody(adminJwt)),
                String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
    }

    @Test
    void get_asViewer_returns403() {
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.GET,
                new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)),
                String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
    }

    @Test
    void put_savesAndReturnsKeys() throws Exception {
        String json = """
                { "keys": ["Authorization", "Cookie", "*password*"] }
                """;
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.PUT,
                new HttpEntity<>(json, securityHelper.authHeaders(adminJwt)),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JsonNode body = objectMapper.readTree(response.getBody());
        assertThat(body.path("keys").size()).isEqualTo(3);
        assertThat(body.path("keys").get(0).asText()).isEqualTo("Authorization");
        assertThat(body.path("pushResult").isNull()).isTrue();
    }

    @Test
    void put_thenGet_returnsStoredKeys() throws Exception {
        String json = """
                { "keys": ["Authorization", "*secret*"] }
                """;
        restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.PUT,
                new HttpEntity<>(json, securityHelper.authHeaders(adminJwt)),
                String.class);

        ResponseEntity<String> getResponse = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.GET,
                new HttpEntity<>(securityHelper.authHeadersNoBody(adminJwt)),
                String.class);

        assertThat(getResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
        JsonNode body = objectMapper.readTree(getResponse.getBody());
        assertThat(body.path("keys").size()).isEqualTo(2);
    }

    @Test
    void put_withPushToAgents_returnsPushResult() throws Exception {
        // The fan-out iterates every distinct (application, environment) slice
        // in the registry. In an isolated test the registry is empty and total
        // is 0, but in the shared Spring context every earlier IT's registered
        // agent shows up here — so we assert the structural shape only.
        String json = """
                { "keys": ["Authorization"] }
                """;
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys?pushToAgents=true", HttpMethod.PUT,
                new HttpEntity<>(json, securityHelper.authHeaders(adminJwt)),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JsonNode body = objectMapper.readTree(response.getBody());
        assertThat(body.path("pushResult").has("total")).isTrue();
        assertThat(body.path("pushResult").path("total").asInt()).isGreaterThanOrEqualTo(0);
    }

    @Test
    void put_asViewer_returns403() {
        String json = """
                { "keys": ["Authorization"] }
                """;
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/sensitive-keys", HttpMethod.PUT,
                new HttpEntity<>(json, securityHelper.authHeaders(viewerJwt)),
                String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
    }
}
