package com.imprimelibros.erp.datatables;

import org.springframework.data.jpa.domain.Specification;
import jakarta.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

public class DataTablesSpecification {

    /**
     * Crea una Specification con búsqueda global y por columna (LIKE
     * case-insensitive)
     * 
     * @param dt               request de datatables
     * @param searchableFields campos del entity para el buscador global
     */
    public static <T> Specification<T> build(DataTablesRequest dt, List<String> searchableFields) {
        return (root, query, cb) -> {
            List<Predicate> ands = new ArrayList<>();

            // Filtro por columna (si lo usas en el cliente)
            for (int i = 0; i < dt.columns.size(); i++) {
                DataTablesRequest.Column col = dt.columns.get(i);
                if (col.searchable && col.search != null && col.search.value != null && !col.search.value.isEmpty()) {
                    try {
                        ands.add(like(cb, root.get(col.name), col.search.value));
                    } catch (IllegalArgumentException ex) {
                        // columna no mapeada o relación: la ignoramos
                    }
                }
            }

            // Búsqueda global
            if (dt.search != null && dt.search.value != null && !dt.search.value.isEmpty()
                    && !searchableFields.isEmpty()) {
                String term = "%" + dt.search.value.trim().toLowerCase() + "%";
                List<Predicate> ors = new ArrayList<>();
                for (String f : searchableFields) {
                    try {
                        ors.add(cb.like(cb.lower(root.get(f).as(String.class)), term));
                    } catch (IllegalArgumentException ex) {
                        // campo no simple: lo saltamos
                    }
                }
                if (!ors.isEmpty())
                    ands.add(cb.or(ors.toArray(new Predicate[0])));
            }

            return ands.isEmpty() ? cb.conjunction() : cb.and(ands.toArray(new Predicate[0]));
        };
    }

    private static Predicate like(CriteriaBuilder cb, Path<?> path, String value) {
        return cb.like(cb.lower(path.as(String.class)), "%" + value.trim().toLowerCase() + "%");
    }
}
