package dev.lions.unionflow.server.resource;

import dev.lions.unionflow.server.api.dto.dashboard.DashboardDataResponse;
import dev.lions.unionflow.server.api.dto.dashboard.DashboardStatsResponse;
import dev.lions.unionflow.server.api.dto.dashboard.RecentActivityResponse;
import dev.lions.unionflow.server.api.dto.dashboard.UpcomingEventResponse;
import dev.lions.unionflow.server.api.service.dashboard.DashboardService;
import jakarta.inject.Inject;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Resource REST pour les APIs du dashboard
 * 
 * <p>Cette ressource expose les endpoints pour récupérer les données du dashboard,
 * incluant les statistiques, activités récentes et événements à venir.
 * 
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-15
 */
@Path("/api/v1/dashboard")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Dashboard", description = "APIs pour la gestion du dashboard")
@RolesAllowed({"ADMIN", "ADMIN_ORGANISATION", "MEMBRE", "USER", "SUPER_ADMIN"})
public class DashboardResource {

    private static final Logger LOG = Logger.getLogger(DashboardResource.class);

    @Inject
    DashboardService dashboardService;

    /**
     * Récupère toutes les données du dashboard
     */
    @GET
    @Path("/data")
    @Operation(
        summary = "Récupérer toutes les données du dashboard",
        description = "Retourne les statistiques, activités récentes et événements à venir"
    )
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Données récupérées avec succès"),
        @APIResponse(responseCode = "400", description = "Paramètres invalides"),
        @APIResponse(responseCode = "500", description = "Erreur serveur")
    })
    public Response getDashboardData(
            @Parameter(description = "ID de l'organisation", required = true)
            @QueryParam("organizationId") @NotNull String organizationId,
            @Parameter(description = "ID de l'utilisateur", required = true)
            @QueryParam("userId") @NotNull String userId) {
        
        LOG.infof("GET /api/v1/dashboard/data - org: %s, user: %s", organizationId, userId);
        
        try {
            DashboardDataResponse dashboardData = dashboardService.getDashboardData(organizationId, userId);
            return Response.ok(dashboardData).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la récupération des données dashboard");
            return Response.serverError().entity(Map.of("error", "Erreur serveur")).build();
        }
    }

    /**
     * Récupère uniquement les statistiques du dashboard
     */
    @GET
    @Path("/stats")
    @Operation(
        summary = "Récupérer les statistiques du dashboard",
        description = "Retourne uniquement les statistiques principales"
    )
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Statistiques récupérées avec succès"),
        @APIResponse(responseCode = "400", description = "Paramètres invalides"),
        @APIResponse(responseCode = "500", description = "Erreur serveur")
    })
    public Response getDashboardStats(
            @Parameter(description = "ID de l'organisation", required = true)
            @QueryParam("organizationId") @NotNull String organizationId,
            @Parameter(description = "ID de l'utilisateur", required = true)
            @QueryParam("userId") @NotNull String userId) {
        
        LOG.infof("GET /api/v1/dashboard/stats - org: %s, user: %s", organizationId, userId);
        
        try {
            DashboardStatsResponse stats = dashboardService.getDashboardStats(organizationId, userId);
            return Response.ok(stats).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la récupération des statistiques dashboard");
            return Response.serverError().entity(Map.of("error", "Erreur serveur")).build();
        }
    }

    /**
     * Récupère les activités récentes
     */
    @GET
    @Path("/activities")
    @Operation(
        summary = "Récupérer les activités récentes",
        description = "Retourne la liste des activités récentes avec pagination"
    )
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Activités récupérées avec succès"),
        @APIResponse(responseCode = "400", description = "Paramètres invalides"),
        @APIResponse(responseCode = "500", description = "Erreur serveur")
    })
    public Response getRecentActivities(
            @Parameter(description = "ID de l'organisation", required = true)
            @QueryParam("organizationId") @NotNull String organizationId,
            @Parameter(description = "ID de l'utilisateur", required = true)
            @QueryParam("userId") @NotNull String userId,
            @Parameter(description = "Nombre maximum d'activités à retourner", required = false)
            @QueryParam("limit") @DefaultValue("10") int limit) {
        
        LOG.infof("GET /api/v1/dashboard/activities - org: %s, user: %s, limit: %d", 
                organizationId, userId, limit);
        
        try {
            List<RecentActivityResponse> activities = dashboardService.getRecentActivities(
                organizationId, userId, limit);
            
            Map<String, Object> response = new HashMap<>();
            response.put("activities", activities);
            response.put("total", activities.size());
            response.put("limit", limit);
            
            return Response.ok(response).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la récupération des activités récentes");
            return Response.serverError().entity(Map.of("error", "Erreur serveur")).build();
        }
    }

    /**
     * Récupère les événements à venir
     */
    @GET
    @Path("/events/upcoming")
    @Operation(
        summary = "Récupérer les événements à venir",
        description = "Retourne la liste des événements à venir avec pagination"
    )
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Événements récupérés avec succès"),
        @APIResponse(responseCode = "400", description = "Paramètres invalides"),
        @APIResponse(responseCode = "500", description = "Erreur serveur")
    })
    public Response getUpcomingEvents(
            @Parameter(description = "ID de l'organisation", required = true)
            @QueryParam("organizationId") @NotNull String organizationId,
            @Parameter(description = "ID de l'utilisateur", required = true)
            @QueryParam("userId") @NotNull String userId,
            @Parameter(description = "Nombre maximum d'événements à retourner", required = false)
            @QueryParam("limit") @DefaultValue("5") int limit) {
        
        LOG.infof("GET /api/v1/dashboard/events/upcoming - org: %s, user: %s, limit: %d", 
                organizationId, userId, limit);
        
        try {
            List<UpcomingEventResponse> events = dashboardService.getUpcomingEvents(
                organizationId, userId, limit);
            
            Map<String, Object> response = new HashMap<>();
            response.put("events", events);
            response.put("total", events.size());
            response.put("limit", limit);
            
            return Response.ok(response).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la récupération des événements à venir");
            return Response.serverError().entity(Map.of("error", "Erreur serveur")).build();
        }
    }

    /**
     * Endpoint de santé pour vérifier le statut du dashboard
     */
    @GET
    @Path("/health")
    @Operation(
        summary = "Vérifier la santé du service dashboard",
        description = "Retourne le statut de santé du service dashboard"
    )
    @APIResponse(responseCode = "200", description = "Service en bonne santé")
    public Response healthCheck() {
        LOG.debug("GET /api/v1/dashboard/health");
        
        Map<String, Object> health = new HashMap<>();
        health.put("status", "UP");
        health.put("service", "dashboard");
        health.put("timestamp", System.currentTimeMillis());
        health.put("version", "1.0.0");
        
        return Response.ok(health).build();
    }

    /**
     * Endpoint pour rafraîchir les données du dashboard
     */
    @POST
    @Path("/refresh")
    @Operation(
        summary = "Rafraîchir les données du dashboard",
        description = "Force la mise à jour des données du dashboard"
    )
    @APIResponses(value = {
        @APIResponse(responseCode = "200", description = "Données rafraîchies avec succès"),
        @APIResponse(responseCode = "400", description = "Paramètres invalides"),
        @APIResponse(responseCode = "500", description = "Erreur serveur")
    })
    public Response refreshDashboard(
            @Parameter(description = "ID de l'organisation", required = true)
            @QueryParam("organizationId") @NotNull String organizationId,
            @Parameter(description = "ID de l'utilisateur", required = true)
            @QueryParam("userId") @NotNull String userId) {
        
        LOG.infof("POST /api/v1/dashboard/refresh - org: %s, user: %s", organizationId, userId);
        
        try {
            // Simuler un rafraîchissement (dans un vrai système, cela pourrait vider le cache)
            DashboardDataResponse dashboardData = dashboardService.getDashboardData(organizationId, userId);
            
            Map<String, Object> response = new HashMap<>();
            response.put("status", "refreshed");
            response.put("timestamp", System.currentTimeMillis());
            response.put("data", dashboardData);
            
            return Response.ok(response).build();
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du rafraîchissement du dashboard");
            return Response.serverError().entity(Map.of("error", "Erreur serveur")).build();
        }
    }
}

