package dev.lions.user.manager.dto.user;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import io.quarkus.runtime.annotations.RegisterForReflection;

import java.io.Serializable;
import java.util.List;

/**
 * Résultat paginé de recherche d'utilisateurs
 * Contient la liste des utilisateurs et les métadonnées de pagination
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(description = "Résultat paginé de recherche d'utilisateurs")
@RegisterForReflection
public class UserSearchResultDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    @Schema(description = "Liste des utilisateurs trouvés")
    private List<UserDTO> users;

    @Schema(description = "Nombre total d'utilisateurs correspondant aux critères", example = "156")
    private Long totalCount;

    @Schema(description = "Numéro de la page actuelle (commence à 0)", example = "0")
    private Integer currentPage;

    @Schema(description = "Taille de la page", example = "20")
    private Integer pageSize;

    @Schema(description = "Nombre total de pages", example = "8")
    private Integer totalPages;

    @Schema(description = "Indique s'il y a une page suivante", example = "true")
    private Boolean hasNextPage;

    @Schema(description = "Indique s'il y a une page précédente", example = "false")
    private Boolean hasPreviousPage;

    @Schema(description = "Index du premier élément de la page", example = "0")
    private Integer firstElement;

    @Schema(description = "Index du dernier élément de la page", example = "19")
    private Integer lastElement;

    @Schema(description = "Indique si la page est vide", example = "false")
    private Boolean isEmpty;

    @Schema(description = "Indique si c'est la première page", example = "true")
    private Boolean isFirstPage;

    @Schema(description = "Indique si c'est la dernière page", example = "false")
    private Boolean isLastPage;

    @Schema(description = "Critères de recherche utilisés")
    private UserSearchCriteriaDTO criteria;

    @Schema(description = "Temps d'exécution de la recherche en millisecondes", example = "145")
    private Long executionTimeMs;

    /**
     * Construit un résultat de recherche à partir d'une liste d'utilisateurs
     * @param users liste des utilisateurs
     * @param criteria critères de recherche
     * @param totalCount nombre total de résultats
     * @return UserSearchResultDTO
     */
    public static UserSearchResultDTO of(List<UserDTO> users, UserSearchCriteriaDTO criteria, Long totalCount) {
        int pageSize = criteria.getPageSize();
        int currentPage = criteria.getPage();
        long totalPages = (totalCount + pageSize - 1) / pageSize;

        return UserSearchResultDTO.builder()
            .users(users)
            .totalCount(totalCount)
            .currentPage(currentPage)
            .pageSize(pageSize)
            .totalPages((int) totalPages)
            .hasNextPage(currentPage < totalPages - 1)
            .hasPreviousPage(currentPage > 0)
            .firstElement(currentPage * pageSize)
            .lastElement(Math.min((currentPage + 1) * pageSize - 1, totalCount.intValue()))
            .isEmpty(users == null || users.isEmpty())
            .isFirstPage(currentPage == 0)
            .isLastPage(currentPage >= totalPages - 1)
            .criteria(criteria)
            .build();
    }

    /**
     * Retourne le nombre d'utilisateurs dans la page courante
     * @return nombre d'utilisateurs
     */
    public int getCurrentPageSize() {
        return users != null ? users.size() : 0;
    }
}
