package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.Budget;
import io.quarkus.arc.Unremovable;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.TypedQuery;
import java.util.List;
import java.util.UUID;

/**
 * Repository pour la gestion des budgets
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-13
 */
@ApplicationScoped
@Unremovable
public class BudgetRepository extends BaseRepository<Budget> {

    public BudgetRepository() {
        super(Budget.class);
    }

    /**
     * Trouve tous les budgets d'une organisation
     *
     * @param organisationId ID de l'organisation
     * @return Liste des budgets
     */
    public List<Budget> findByOrganisation(UUID organisationId) {
        return entityManager.createQuery(
                "SELECT b FROM Budget b WHERE b.organisation.id = :orgId ORDER BY b.year DESC, b.month DESC",
                Budget.class)
            .setParameter("orgId", organisationId)
            .getResultList();
    }

    /**
     * Trouve les budgets d'une organisation avec filtres
     *
     * @param organisationId ID de l'organisation
     * @param status Statut (optionnel)
     * @param year Année (optionnel)
     * @return Liste des budgets
     */
    public List<Budget> findByOrganisationWithFilters(
            UUID organisationId,
            String status,
            Integer year) {

        StringBuilder jpql = new StringBuilder(
            "SELECT b FROM Budget b WHERE b.organisation.id = :orgId");

        if (status != null && !status.isEmpty()) {
            jpql.append(" AND b.status = :status");
        }
        if (year != null) {
            jpql.append(" AND b.year = :year");
        }

        jpql.append(" ORDER BY b.year DESC, b.month DESC");

        TypedQuery<Budget> query = entityManager.createQuery(jpql.toString(), Budget.class);
        query.setParameter("orgId", organisationId);

        if (status != null && !status.isEmpty()) {
            query.setParameter("status", status);
        }
        if (year != null) {
            query.setParameter("year", year);
        }

        return query.getResultList();
    }

    /**
     * Trouve le budget actif pour une organisation
     *
     * @param organisationId ID de l'organisation
     * @return Liste des budgets actifs
     */
    public List<Budget> findActiveByOrganisation(UUID organisationId) {
        return entityManager.createQuery(
                "SELECT b FROM Budget b WHERE b.organisation.id = :orgId AND b.status = 'ACTIVE' " +
                "ORDER BY b.year DESC, b.month DESC",
                Budget.class)
            .setParameter("orgId", organisationId)
            .getResultList();
    }

    /**
     * Trouve les budgets d'une année pour une organisation
     *
     * @param organisationId ID de l'organisation
     * @param year Année
     * @return Liste des budgets
     */
    public List<Budget> findByOrganisationAndYear(UUID organisationId, int year) {
        return entityManager.createQuery(
                "SELECT b FROM Budget b WHERE b.organisation.id = :orgId AND b.year = :year " +
                "ORDER BY b.month ASC",
                Budget.class)
            .setParameter("orgId", organisationId)
            .setParameter("year", year)
            .getResultList();
    }

    /**
     * Compte les budgets actifs pour une organisation
     *
     * @param organisationId ID de l'organisation
     * @return Nombre de budgets actifs
     */
    public long countActiveByOrganisation(UUID organisationId) {
        return entityManager.createQuery(
                "SELECT COUNT(b) FROM Budget b WHERE b.organisation.id = :orgId AND b.status = 'ACTIVE'",
                Long.class)
            .setParameter("orgId", organisationId)
            .getSingleResult();
    }
}
