package com.cameleer.server.app.license;

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;

/**
 * Verifies that the {@code max_environments} cap from the default tier is enforced at
 * {@code POST /api/v1/admin/environments}. Default tier {@code max_environments = 1}; the V1
 * baseline migration seeds a single {@code default} environment, so the very next create
 * attempt must be rejected with the structured 403 envelope produced by
 * {@link LicenseExceptionAdvice}.
 */
class EnvironmentCapEnforcementIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private TestSecurityHelper securityHelper;

    private String adminJwt;

    @BeforeEach
    void setUp() {
        adminJwt = securityHelper.adminToken();
        // Defensive: clear any license a previous IT may have left installed (each IT gets its own
        // Spring context only on first @SpringBootTest reuse boundary; LicenseGate is a singleton).
        securityHelper.clearTestLicense();
        // Ensure starting state: only the seeded "default" env (count = 1, equals the cap).
        // Strip dependents first — sibling ITs may have left deployments/apps that FK back to
        // non-default envs when the testcontainer is reused across runs.
        jdbcTemplate.update("DELETE FROM deployments");
        jdbcTemplate.update("DELETE FROM app_versions");
        jdbcTemplate.update("DELETE FROM apps");
        jdbcTemplate.update("DELETE FROM environments WHERE slug != 'default'");
    }

    @Test
    void createBeyondCap_returns403WithStateAndMessage() throws Exception {
        // Default tier: max_environments = 1; V1 seeds the default env, so the next create rejects.
        String json = """
                {"slug":"prod","displayName":"Prod","production":true}
                """;

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/environments", HttpMethod.POST,
                new HttpEntity<>(json, securityHelper.authHeaders(adminJwt)),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
        JsonNode body = objectMapper.readTree(response.getBody());
        assertThat(body.path("error").asText()).isEqualTo("license cap reached");
        assertThat(body.path("limit").asText()).isEqualTo("max_environments");
        assertThat(body.path("cap").asInt()).isEqualTo(1);
        assertThat(body.path("state").asText()).isEqualTo("ABSENT");
        assertThat(body.has("message")).isTrue();
        assertThat(body.path("message").asText()).isNotBlank();

        // And the env was not created.
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM environments WHERE slug = 'prod'", Integer.class);
        assertThat(count).isZero();
    }
}
