package io.cameleer.server.app.controller;

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

import java.util.Map;

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

/**
 * IT for {@code GET /api/v1/admin/license/usage}.
 *
 * <p>Installs a synthetic license with a couple of cap overrides (so the {@code source}
 * column is exercised in both branches), then verifies the response shape.</p>
 */
class LicenseUsageControllerIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private TestSecurityHelper securityHelper;

    private String adminJwt;

    @BeforeEach
    void setUp() {
        adminJwt = securityHelper.adminToken();
        // Defensive: a sibling IT may have left a license installed.
        securityHelper.clearTestLicense();
    }

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

    @Test
    void getUsage_withSyntheticLicense_returnsStateAndLimits() throws Exception {
        // Override two keys; the rest stay default.
        securityHelper.installSyntheticUnsignedLicense(Map.of(
                "max_apps", 50,
                "max_users", 100));

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/license/usage", HttpMethod.GET,
                new HttpEntity<>(securityHelper.authHeadersNoBody(adminJwt)),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JsonNode body = objectMapper.readTree(response.getBody());

        assertThat(body.path("state").asText()).isEqualTo("ACTIVE");
        assertThat(body.path("tenantId").asText()).isEqualTo("default");
        assertThat(body.path("label").asText()).isEqualTo("test-license");
        assertThat(body.path("message").asText()).isNotBlank();

        JsonNode limits = body.path("limits");
        assertThat(limits.isArray()).isTrue();
        assertThat(limits.size()).isGreaterThan(0);

        boolean sawLicenseSource = false;
        boolean sawDefaultSource = false;
        boolean sawAppsRow = false;
        boolean sawUsersRow = false;
        for (JsonNode row : limits) {
            assertThat(row.has("key")).isTrue();
            assertThat(row.has("current")).isTrue();
            assertThat(row.has("cap")).isTrue();
            assertThat(row.has("source")).isTrue();

            String src = row.path("source").asText();
            if ("license".equals(src)) sawLicenseSource = true;
            if ("default".equals(src)) sawDefaultSource = true;

            if ("max_apps".equals(row.path("key").asText())) {
                sawAppsRow = true;
                assertThat(row.path("source").asText()).isEqualTo("license");
                assertThat(row.path("cap").asInt()).isEqualTo(50);
            }
            if ("max_users".equals(row.path("key").asText())) {
                sawUsersRow = true;
                assertThat(row.path("source").asText()).isEqualTo("license");
                assertThat(row.path("cap").asInt()).isEqualTo(100);
            }
        }
        assertThat(sawLicenseSource).as("at least one license-sourced row").isTrue();
        assertThat(sawDefaultSource).as("at least one default-sourced row").isTrue();
        assertThat(sawAppsRow).as("max_apps row present").isTrue();
        assertThat(sawUsersRow).as("max_users row present").isTrue();
    }

    @Test
    void getUsage_absent_returnsAbsentStateAndDefaultSources() throws Exception {
        // No license installed (cleared in @BeforeEach).
        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/admin/license/usage", HttpMethod.GET,
                new HttpEntity<>(securityHelper.authHeadersNoBody(adminJwt)),
                String.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JsonNode body = objectMapper.readTree(response.getBody());

        assertThat(body.path("state").asText()).isEqualTo("ABSENT");
        assertThat(body.path("tenantId").isNull()).isTrue();
        assertThat(body.path("expiresAt").isNull()).isTrue();
        assertThat(body.path("message").asText()).isNotBlank();

        JsonNode limits = body.path("limits");
        assertThat(limits.isArray()).isTrue();
        assertThat(limits.size()).isGreaterThan(0);
        for (JsonNode row : limits) {
            assertThat(row.path("source").asText()).isEqualTo("default");
        }
    }
}
