package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.admin.request.CreateAuditLogRequest;
import dev.lions.unionflow.server.api.dto.admin.response.AuditLogResponse;
import dev.lions.unionflow.server.service.AuditService;
import jakarta.inject.Inject;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDateTime;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

/**
 * Resource REST pour la gestion des logs d'audit
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-17
 */
@Path("/api/audit")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Audit", description = "Gestion des logs d'audit")
@Slf4j
@RolesAllowed({ "ADMIN", "SUPER_ADMIN", "ADMIN_ORGANISATION" })
public class AuditResource {

    @Inject
    AuditService auditService;

    @GET
    @Operation(summary = "Liste tous les logs d'audit", description = "Récupère tous les logs avec pagination")
    public Response listerTous(
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("50") int size,
            @QueryParam("sortBy") @DefaultValue("dateHeure") String sortBy,
            @QueryParam("sortOrder") @DefaultValue("desc") String sortOrder) {

        try {
            Map<String, Object> result = auditService.listerTous(page, size, sortBy, sortOrder);
            return Response.ok(result).build();
        } catch (Exception e) {
            log.error("Erreur lors de la récupération des logs d'audit", e);
            return Response.serverError()
                    .entity(Map.of("error", "Erreur lors de la récupération des logs: " + e.getMessage()))
                    .build();
        }
    }

    @POST
    @Path("/rechercher")
    @Operation(summary = "Recherche des logs avec filtres", description = "Recherche avancée avec filtres multiples")
    public Response rechercher(
            @QueryParam("dateDebut") String dateDebutStr,
            @QueryParam("dateFin") String dateFinStr,
            @QueryParam("typeAction") String typeAction,
            @QueryParam("severite") String severite,
            @QueryParam("utilisateur") String utilisateur,
            @QueryParam("module") String module,
            @QueryParam("ipAddress") String ipAddress,
            @QueryParam("page") @DefaultValue("0") int page,
            @QueryParam("size") @DefaultValue("50") int size) {

        try {
            LocalDateTime dateDebut = dateDebutStr != null ? LocalDateTime.parse(dateDebutStr) : null;
            LocalDateTime dateFin = dateFinStr != null ? LocalDateTime.parse(dateFinStr) : null;

            Map<String, Object> result = auditService.rechercher(
                    dateDebut, dateFin, typeAction, severite, utilisateur, module, ipAddress, page, size);
            return Response.ok(result).build();
        } catch (Exception e) {
            log.error("Erreur lors de la recherche des logs d'audit", e);
            return Response.serverError()
                    .entity(Map.of("error", "Erreur lors de la recherche: " + e.getMessage()))
                    .build();
        }
    }

    @POST
    @Operation(summary = "Enregistre un nouveau log d'audit", description = "Crée une nouvelle entrée dans le journal d'audit")
    public Response enregistrerLog(@Valid CreateAuditLogRequest request) {
        try {
            AuditLogResponse result = auditService.enregistrerLog(request);
            return Response.status(Response.Status.CREATED).entity(result).build();
        } catch (Exception e) {
            log.error("Erreur lors de l'enregistrement du log d'audit", e);
            return Response.serverError()
                    .entity(Map.of("error", "Erreur lors de l'enregistrement: " + e.getMessage()))
                    .build();
        }
    }

    @GET
    @Path("/statistiques")
    @Operation(summary = "Récupère les statistiques d'audit", description = "Retourne les statistiques globales des logs")
    public Response getStatistiques() {
        try {
            Map<String, Object> stats = auditService.getStatistiques();
            return Response.ok(stats).build();
        } catch (Exception e) {
            log.error("Erreur lors de la récupération des statistiques", e);
            return Response.serverError()
                    .entity(Map.of("error", "Erreur lors de la récupération des statistiques: " + e.getMessage()))
                    .build();
        }
    }
}
