package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.SystemLog;
import io.quarkus.arc.Unremovable;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional;

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

/**
 * Repository pour l'entité SystemLog
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-15
 */
@ApplicationScoped
@Unremovable
public class SystemLogRepository extends BaseRepository<SystemLog> {

    public SystemLogRepository() {
        super(SystemLog.class);
    }

    /**
     * Rechercher les logs par niveau
     */
    public List<SystemLog> findByLevel(String level) {
        TypedQuery<SystemLog> query = entityManager.createQuery(
                "SELECT l FROM SystemLog l WHERE l.level = :level ORDER BY l.timestamp DESC",
                SystemLog.class
        );
        query.setParameter("level", level);
        return query.getResultList();
    }

    /**
     * Rechercher les logs par source
     */
    public List<SystemLog> findBySource(String source) {
        TypedQuery<SystemLog> query = entityManager.createQuery(
                "SELECT l FROM SystemLog l WHERE l.source = :source ORDER BY l.timestamp DESC",
                SystemLog.class
        );
        query.setParameter("source", source);
        return query.getResultList();
    }

    /**
     * Rechercher les logs par niveau et source
     */
    public List<SystemLog> findByLevelAndSource(String level, String source) {
        TypedQuery<SystemLog> query = entityManager.createQuery(
                "SELECT l FROM SystemLog l WHERE l.level = :level AND l.source = :source ORDER BY l.timestamp DESC",
                SystemLog.class
        );
        query.setParameter("level", level);
        query.setParameter("source", source);
        return query.getResultList();
    }

    /**
     * Rechercher les logs par période
     */
    public List<SystemLog> findByTimestampBetween(LocalDateTime start, LocalDateTime end) {
        TypedQuery<SystemLog> query = entityManager.createQuery(
                "SELECT l FROM SystemLog l WHERE l.timestamp BETWEEN :start AND :end ORDER BY l.timestamp DESC",
                SystemLog.class
        );
        query.setParameter("start", start);
        query.setParameter("end", end);
        return query.getResultList();
    }

    /**
     * Rechercher les logs contenant un texte
     */
    public List<SystemLog> searchByText(String searchQuery) {
        TypedQuery<SystemLog> query = entityManager.createQuery(
                "SELECT l FROM SystemLog l WHERE LOWER(l.message) LIKE LOWER(:query) OR LOWER(l.source) LIKE LOWER(:query) ORDER BY l.timestamp DESC",
                SystemLog.class
        );
        query.setParameter("query", "%" + searchQuery + "%");
        return query.getResultList();
    }

    /**
     * Recherche avancée avec tous les filtres
     */
    public List<SystemLog> search(String level, String source, String searchQuery, LocalDateTime start, LocalDateTime end, int pageIndex, int pageSize) {
        StringBuilder jpql = new StringBuilder("SELECT l FROM SystemLog l WHERE 1=1");

        if (level != null && !level.isBlank() && !"TOUS".equals(level)) {
            jpql.append(" AND l.level = :level");
        }
        if (source != null && !source.isBlank() && !"TOUS".equals(source)) {
            jpql.append(" AND l.source = :source");
        }
        if (searchQuery != null && !searchQuery.isBlank()) {
            jpql.append(" AND (LOWER(l.message) LIKE LOWER(:query) OR LOWER(l.source) LIKE LOWER(:query))");
        }
        if (start != null) {
            jpql.append(" AND l.timestamp >= :start");
        }
        if (end != null) {
            jpql.append(" AND l.timestamp <= :end");
        }

        jpql.append(" ORDER BY l.timestamp DESC");

        TypedQuery<SystemLog> query = entityManager.createQuery(jpql.toString(), SystemLog.class);

        if (level != null && !level.isBlank() && !"TOUS".equals(level)) {
            query.setParameter("level", level);
        }
        if (source != null && !source.isBlank() && !"TOUS".equals(source)) {
            query.setParameter("source", source);
        }
        if (searchQuery != null && !searchQuery.isBlank()) {
            query.setParameter("query", "%" + searchQuery + "%");
        }
        if (start != null) {
            query.setParameter("start", start);
        }
        if (end != null) {
            query.setParameter("end", end);
        }

        query.setFirstResult(pageIndex * pageSize);
        query.setMaxResults(pageSize);

        return query.getResultList();
    }

    /**
     * Compter les logs par niveau dans les dernières 24h
     */
    public long countByLevelLast24h(String level) {
        LocalDateTime yesterday = LocalDateTime.now().minusHours(24);
        TypedQuery<Long> query = entityManager.createQuery(
                "SELECT COUNT(l) FROM SystemLog l WHERE l.level = :level AND l.timestamp >= :yesterday",
                Long.class
        );
        query.setParameter("level", level);
        query.setParameter("yesterday", yesterday);
        return query.getSingleResult();
    }

    /**
     * Supprimer les logs plus anciens qu'une date donnée (rotation).
     * Requiert une transaction active — DELETE via JPQL doit être transactionnel.
     */
    @Transactional
    public int deleteOlderThan(LocalDateTime threshold) {
        return entityManager.createQuery(
                "DELETE FROM SystemLog l WHERE l.timestamp < :threshold"
        )
        .setParameter("threshold", threshold)
        .executeUpdate();
    }
}
