package dev.lions.unionflow.server.resource;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;

import dev.lions.unionflow.server.api.dto.logs.request.LogSearchRequest;
import dev.lions.unionflow.server.api.dto.logs.request.UpdateAlertConfigRequest;
import dev.lions.unionflow.server.api.dto.logs.response.AlertConfigResponse;
import dev.lions.unionflow.server.api.dto.logs.response.SystemAlertResponse;
import dev.lions.unionflow.server.api.dto.logs.response.SystemLogResponse;
import dev.lions.unionflow.server.api.dto.logs.response.SystemMetricsResponse;
import dev.lions.unionflow.server.service.LogsMonitoringService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;

/**
 * Tests d'intégration REST pour LogsMonitoringResource.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-21
 */
@QuarkusTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class LogsMonitoringResourceTest {

    private static final String ALERT_ID = "00000000-0000-0000-0000-000000000001";

    @InjectMock
    LogsMonitoringService logsMonitoringService;

    // -------------------------------------------------------------------------
    // POST /api/logs/search
    // -------------------------------------------------------------------------

    @Test
    @Order(1)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void searchLogs_success_returns200() {
        SystemLogResponse logResponse = SystemLogResponse.builder()
                .level("ERROR")
                .source("api")
                .message("Test log message")
                .build();
        when(logsMonitoringService.searchLogs(any(LogSearchRequest.class)))
                .thenReturn(List.of(logResponse));

        String body = """
                {"level":"ERROR","source":"api","timeRange":"24H","offset":0,"limit":50}
                """;

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .post("/api/logs/search")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("$", notNullValue());
    }

    @Test
    @Order(2)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void searchLogs_emptyResult_returns200() {
        when(logsMonitoringService.searchLogs(any(LogSearchRequest.class)))
                .thenReturn(Collections.emptyList());

        String body = """
                {"level":"DEBUG","source":"auth","timeRange":"1H","offset":0,"limit":100}
                """;

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .post("/api/logs/search")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @Order(3)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void searchLogs_serverError_returns500() {
        when(logsMonitoringService.searchLogs(any(LogSearchRequest.class)))
                .thenThrow(new RuntimeException("db error"));

        String body = """
                {"level":"ERROR","timeRange":"7D","offset":0,"limit":100}
                """;

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .post("/api/logs/search")
                .then()
                .statusCode(500);
    }

    // -------------------------------------------------------------------------
    // GET /api/logs/export
    // -------------------------------------------------------------------------

    @Test
    @Order(4)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void exportLogs_success_returns200() {
        SystemLogResponse logResponse = SystemLogResponse.builder()
                .level("INFO")
                .source("api")
                .message("Export test")
                .details(null)
                .build();
        when(logsMonitoringService.searchLogs(any(LogSearchRequest.class)))
                .thenReturn(List.of(logResponse));

        given()
                .queryParam("level", "INFO")
                .queryParam("source", "api")
                .queryParam("timeRange", "24H")
                .when()
                .get("/api/logs/export")
                .then()
                .statusCode(200);
    }

    @Test
    @Order(5)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void exportLogs_noParams_returns200() {
        when(logsMonitoringService.searchLogs(any(LogSearchRequest.class)))
                .thenReturn(Collections.emptyList());

        given()
                .when()
                .get("/api/logs/export")
                .then()
                .statusCode(200);
    }

    // -------------------------------------------------------------------------
    // GET /api/monitoring/metrics
    // -------------------------------------------------------------------------

    @Test
    @Order(6)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getSystemMetrics_success_returns200() {
        SystemMetricsResponse metrics = SystemMetricsResponse.builder()
                .cpuUsagePercent(45.0)
                .memoryUsagePercent(60.0)
                .diskUsagePercent(40.0)
                .build();
        when(logsMonitoringService.getSystemMetrics()).thenReturn(metrics);

        given()
                .when()
                .get("/api/monitoring/metrics")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("$", notNullValue());
    }

    @Test
    @Order(7)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getSystemMetrics_serverError_returns500() {
        when(logsMonitoringService.getSystemMetrics())
                .thenThrow(new RuntimeException("metrics unavailable"));

        given()
                .when()
                .get("/api/monitoring/metrics")
                .then()
                .statusCode(500);
    }

    // -------------------------------------------------------------------------
    // GET /api/alerts
    // -------------------------------------------------------------------------

    @Test
    @Order(8)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getActiveAlerts_success_returns200() {
        SystemAlertResponse alert = SystemAlertResponse.builder()
                .level("WARNING")
                .title("CPU High")
                .message("CPU above threshold")
                .acknowledged(false)
                .build();
        when(logsMonitoringService.getActiveAlerts()).thenReturn(List.of(alert));

        given()
                .when()
                .get("/api/alerts")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("$", notNullValue());
    }

    @Test
    @Order(9)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getActiveAlerts_empty_returns200() {
        when(logsMonitoringService.getActiveAlerts()).thenReturn(Collections.emptyList());

        given()
                .when()
                .get("/api/alerts")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    // -------------------------------------------------------------------------
    // POST /api/alerts/{id}/acknowledge
    // -------------------------------------------------------------------------

    @Test
    @Order(10)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void acknowledgeAlert_success_returns200() {
        doNothing().when(logsMonitoringService).acknowledgeAlert(any(UUID.class));

        given()
                .pathParam("id", ALERT_ID)
                .contentType(ContentType.JSON)
                .when()
                .post("/api/alerts/{id}/acknowledge")
                .then()
                .statusCode(200)
                .body("message", notNullValue());
    }

    @Test
    @Order(11)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void acknowledgeAlert_serverError_returns500() {
        when(logsMonitoringService.getActiveAlerts())
                .thenThrow(new RuntimeException("ack error"));
        org.mockito.Mockito.doThrow(new RuntimeException("ack error"))
                .when(logsMonitoringService).acknowledgeAlert(any(UUID.class));

        given()
                .pathParam("id", ALERT_ID)
                .contentType(ContentType.JSON)
                .when()
                .post("/api/alerts/{id}/acknowledge")
                .then()
                .statusCode(500);
    }

    // -------------------------------------------------------------------------
    // GET /api/alerts/config
    // -------------------------------------------------------------------------

    @Test
    @Order(12)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getAlertConfig_success_returns200() {
        AlertConfigResponse config = AlertConfigResponse.builder()
                .cpuHighAlertEnabled(true)
                .cpuThresholdPercent(85)
                .memoryLowAlertEnabled(true)
                .memoryThresholdPercent(90)
                .emailNotificationsEnabled(true)
                .activeAlerts(2)
                .totalAlertsLast24h(5)
                .acknowledgedAlerts(3)
                .build();
        when(logsMonitoringService.getAlertConfig()).thenReturn(config);

        given()
                .when()
                .get("/api/alerts/config")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("$", notNullValue());
    }

    @Test
    @Order(13)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void getAlertConfig_serverError_returns500() {
        when(logsMonitoringService.getAlertConfig())
                .thenThrow(new RuntimeException("config error"));

        given()
                .when()
                .get("/api/alerts/config")
                .then()
                .statusCode(500);
    }

    // -------------------------------------------------------------------------
    // PUT /api/alerts/config
    // -------------------------------------------------------------------------

    @Test
    @Order(14)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void updateAlertConfig_success_returns200() {
        AlertConfigResponse config = AlertConfigResponse.builder()
                .cpuHighAlertEnabled(true)
                .cpuThresholdPercent(90)
                .memoryLowAlertEnabled(false)
                .memoryThresholdPercent(85)
                .emailNotificationsEnabled(true)
                .activeAlerts(0)
                .totalAlertsLast24h(1)
                .acknowledgedAlerts(1)
                .build();
        when(logsMonitoringService.updateAlertConfig(any(UpdateAlertConfigRequest.class)))
                .thenReturn(config);

        String body = """
                {
                  "cpuHighAlertEnabled": true,
                  "cpuThresholdPercent": 90,
                  "cpuDurationMinutes": 5,
                  "memoryLowAlertEnabled": false,
                  "memoryThresholdPercent": 85,
                  "criticalErrorAlertEnabled": true,
                  "errorAlertEnabled": true,
                  "connectionFailureAlertEnabled": false,
                  "connectionFailureThreshold": 5,
                  "connectionFailureWindowMinutes": 10,
                  "emailNotificationsEnabled": true,
                  "pushNotificationsEnabled": false,
                  "smsNotificationsEnabled": false
                }
                """;

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .put("/api/alerts/config")
                .then()
                .statusCode(200)
                .contentType(ContentType.JSON)
                .body("$", notNullValue());
    }

    @Test
    @Order(15)
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    void updateAlertConfig_serverError_returns500() {
        when(logsMonitoringService.updateAlertConfig(any(UpdateAlertConfigRequest.class)))
                .thenThrow(new RuntimeException("update error"));

        String body = """
                {"cpuHighAlertEnabled": true, "cpuThresholdPercent": 80}
                """;

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