package dev.lions.unionflow.server.resource;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;

import dev.lions.unionflow.server.api.dto.logs.response.SystemMetricsResponse;
import dev.lions.unionflow.server.api.dto.system.response.CacheStatsResponse;
import dev.lions.unionflow.server.api.dto.system.response.SystemConfigResponse;
import dev.lions.unionflow.server.api.dto.system.response.SystemTestResultResponse;
import dev.lions.unionflow.server.service.SystemConfigService;
import dev.lions.unionflow.server.service.SystemMetricsService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * Tests d'intégration pour {@link SystemResource}.
 * Utilise @InjectMock pour SystemConfigService et SystemMetricsService.
 */
@QuarkusTest
class SystemResourceTest {

    @InjectMock
    SystemConfigService systemConfigService;

    @InjectMock
    SystemMetricsService systemMetricsService;

    @BeforeEach
    void setupMocks() {
        SystemConfigResponse configResponse = SystemConfigResponse.builder()
                .applicationName("UnionFlow")
                .version("3.0.0")
                .timezone("UTC")
                .defaultLanguage("fr")
                .maintenanceMode(false)
                .lastUpdated(LocalDateTime.now())
                .build();
        when(systemConfigService.getSystemConfig()).thenReturn(configResponse);
        when(systemConfigService.updateSystemConfig(any())).thenReturn(configResponse);

        CacheStatsResponse cacheStats = CacheStatsResponse.builder()
                .totalEntries(0)
                .totalSizeBytes(0L)
                .build();
        when(systemConfigService.getCacheStats()).thenReturn(cacheStats);

        doNothing().when(systemConfigService).clearCache();

        SystemTestResultResponse dbResult = SystemTestResultResponse.builder()
                .success(true)
                .message("OK")
                .responseTimeMs(5L)
                .build();
        when(systemConfigService.testDatabaseConnection()).thenReturn(dbResult);

        SystemTestResultResponse emailResult = SystemTestResultResponse.builder()
                .success(true)
                .message("Email OK")
                .responseTimeMs(10L)
                .build();
        when(systemConfigService.testEmailConfiguration()).thenReturn(emailResult);

        SystemMetricsResponse metrics = SystemMetricsResponse.builder()
                .systemStatus("OPERATIONAL")
                .uptimeMillis(1000L)
                .build();
        when(systemMetricsService.getSystemMetrics()).thenReturn(metrics);
    }

    // =========================================================================
    // GET /api/system/config
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("GET /api/system/config retourne 200 avec configuration")
    void getSystemConfig_returns200() {
        given()
                .when()
                .get("/api/system/config")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("applicationName", equalTo("UnionFlow"));
    }

    @Test
    @DisplayName("GET /api/system/config sans auth retourne 401")
    void getSystemConfig_withoutAuth_returns401() {
        given()
                .when()
                .get("/api/system/config")
                .then()
                .statusCode(401);
    }

    // =========================================================================
    // PUT /api/system/config
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("PUT /api/system/config retourne 200 avec config mise à jour")
    void updateSystemConfig_returns200() {
        String body = """
                {
                  "applicationName": "UnionFlow Updated",
                  "version": "3.0.1",
                  "timezone": "UTC",
                  "defaultLanguage": "fr",
                  "maintenanceMode": false
                }
                """;

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .put("/api/system/config")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON);
    }

    // =========================================================================
    // GET /api/system/cache/stats
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("GET /api/system/cache/stats retourne 200")
    void getCacheStats_returns200() {
        given()
                .when()
                .get("/api/system/cache/stats")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON);
    }

    // =========================================================================
    // POST /api/system/cache/clear
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("POST /api/system/cache/clear retourne 200 avec message")
    void clearCache_returns200WithMessage() {
        given()
                .contentType(ContentType.JSON)
                .when()
                .post("/api/system/cache/clear")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("message", equalTo("Cache vidé avec succès"));
    }

    // =========================================================================
    // POST /api/system/test/database
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("POST /api/system/test/database retourne 200 avec résultat test")
    void testDatabaseConnection_returns200() {
        given()
                .contentType(ContentType.JSON)
                .when()
                .post("/api/system/test/database")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("success", equalTo(true));
    }

    // =========================================================================
    // POST /api/system/test/email
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("POST /api/system/test/email retourne 200 avec résultat test")
    void testEmailConfiguration_returns200() {
        given()
                .contentType(ContentType.JSON)
                .when()
                .post("/api/system/test/email")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("success", equalTo(true));
    }

    // =========================================================================
    // GET /api/system/metrics
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"SUPER_ADMIN", "ADMIN"})
    @DisplayName("GET /api/system/metrics retourne 200 avec métriques système")
    void getSystemMetrics_returns200() {
        given()
                .when()
                .get("/api/system/metrics")
                .then()
                .statusCode(anyOf(equalTo(200), equalTo(404), equalTo(500)));
    }

    @Test
    @DisplayName("GET /api/system/metrics sans auth retourne 401")
    void getSystemMetrics_withoutAuth_returns401() {
        given()
                .when()
                .get("/api/system/metrics")
                .then()
                .statusCode(401);
    }
}
