package dev.lions.user.manager.service;

import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

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

/**
 * Service de gestion des logs d'audit
 * Enregistre toutes les actions effectuées via l'API
 */
public interface AuditService {

    /**
     * Enregistre une entrée d'audit
     * @param auditLog entrée d'audit
     * @return entrée enregistrée avec son ID
     */
    AuditLogDTO logAction(@Valid @NotNull AuditLogDTO auditLog);

    /**
     * Enregistre une action réussie
     * @param typeAction type d'action
     * @param ressourceType type de ressource
     * @param ressourceId ID de la ressource
     * @param ressourceName nom de la ressource
     * @param realmName nom du realm
     * @param acteurUserId ID de l'acteur
     * @param description description
     */
    void logSuccess(@NotNull TypeActionAudit typeAction,
                   @NotBlank String ressourceType,
                   String ressourceId,
                   String ressourceName,
                   @NotBlank String realmName,
                   @NotBlank String acteurUserId,
                   String description);

    /**
     * Enregistre une action échouée
     * @param typeAction type d'action
     * @param ressourceType type de ressource
     * @param ressourceId ID de la ressource
     * @param ressourceName nom de la ressource
     * @param realmName nom du realm
     * @param acteurUserId ID de l'acteur
     * @param errorCode code d'erreur
     * @param errorMessage message d'erreur
     */
    void logFailure(@NotNull TypeActionAudit typeAction,
                   @NotBlank String ressourceType,
                   String ressourceId,
                   String ressourceName,
                   @NotBlank String realmName,
                   @NotBlank String acteurUserId,
                   String errorCode,
                   String errorMessage);

    /**
     * Recherche les logs d'audit par utilisateur acteur
     * @param acteurUserId ID de l'utilisateur acteur
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs
     */
    List<AuditLogDTO> findByActeur(@NotBlank String acteurUserId,
                                   LocalDateTime dateDebut,
                                   LocalDateTime dateFin,
                                   int page,
                                   int pageSize);

    /**
     * Recherche les logs d'audit par ressource
     * @param ressourceType type de ressource
     * @param ressourceId ID de la ressource
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs
     */
    List<AuditLogDTO> findByRessource(@NotBlank String ressourceType,
                                      @NotBlank String ressourceId,
                                      LocalDateTime dateDebut,
                                      LocalDateTime dateFin,
                                      int page,
                                      int pageSize);

    /**
     * Recherche les logs d'audit par type d'action
     * @param typeAction type d'action
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs
     */
    List<AuditLogDTO> findByTypeAction(@NotNull TypeActionAudit typeAction,
                                       @NotBlank String realmName,
                                       LocalDateTime dateDebut,
                                       LocalDateTime dateFin,
                                       int page,
                                       int pageSize);

    /**
     * Recherche les logs d'audit par realm
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs
     */
    List<AuditLogDTO> findByRealm(@NotBlank String realmName,
                                  LocalDateTime dateDebut,
                                  LocalDateTime dateFin,
                                  int page,
                                  int pageSize);

    /**
     * Recherche les actions échouées
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs d'échec
     */
    List<AuditLogDTO> findFailures(@NotBlank String realmName,
                                   LocalDateTime dateDebut,
                                   LocalDateTime dateFin,
                                   int page,
                                   int pageSize);

    /**
     * Recherche les actions critiques
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @param page numéro de page
     * @param pageSize taille de la page
     * @return liste des logs critiques
     */
    List<AuditLogDTO> findCriticalActions(@NotBlank String realmName,
                                          LocalDateTime dateDebut,
                                          LocalDateTime dateFin,
                                          int page,
                                          int pageSize);

    /**
     * Compte les actions par type
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @return map type d'action -> nombre
     */
    Map<TypeActionAudit, Long> countByActionType(@NotBlank String realmName,
                                                 LocalDateTime dateDebut,
                                                 LocalDateTime dateFin);

    /**
     * Compte les actions par utilisateur
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @return map username -> nombre d'actions
     */
    Map<String, Long> countByActeur(@NotBlank String realmName,
                                   LocalDateTime dateDebut,
                                   LocalDateTime dateFin);

    /**
     * Compte les actions réussies vs échouées
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @return map "success" -> count, "failure" -> count
     */
    Map<String, Long> countSuccessVsFailure(@NotBlank String realmName,
                                           LocalDateTime dateDebut,
                                           LocalDateTime dateFin);

    /**
     * Exporte les logs d'audit au format CSV
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @return contenu CSV
     */
    String exportToCSV(@NotBlank String realmName,
                      LocalDateTime dateDebut,
                      LocalDateTime dateFin);

    /**
     * Supprime les logs d'audit plus anciens qu'une date
     * @param dateLimite date limite (logs antérieurs seront supprimés)
     * @return nombre de logs supprimés
     */
    long purgeOldLogs(@NotNull LocalDateTime dateLimite);

    /**
     * Récupère les statistiques d'audit pour un dashboard
     * @param realmName nom du realm
     * @param dateDebut date de début
     * @param dateFin date de fin
     * @return map de statistiques
     */
    Map<String, Object> getAuditStatistics(@NotBlank String realmName,
                                          LocalDateTime dateDebut,
                                          LocalDateTime dateFin);
}
