package com.printhub.printhub.utils.datatables;

import org.springframework.data.domain.Page;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


public class DataTableBuilder<T> {

    private final int draw;
    private final Page<T> page;
    private final List<Function<T, Map<String, Object>>> mappers = new ArrayList<>();
    private final Map<String, Function<T, Object>> addedColumns = new HashMap<>();
    private final Map<String, Function<T, Object>> editedColumns = new HashMap<>();

    public DataTableBuilder(Page<T> page, int draw) {
        this.page = page;
        this.draw = draw;
    }

    public DataTableBuilder<T> addColumn(String columnName, Function<T, Object> generator) {
        addedColumns.put(columnName, generator);
        return this;
    }

    public DataTableBuilder<T> editColumn(String columnName, Function<T, Object> replacer) {
        editedColumns.put(columnName, replacer);
        return this;
    }

    public Map<String, Object> build() {
        List<Map<String, Object>> data = page.getContent().stream()
            .map(entity -> {
                Map<String, Object> row = new LinkedHashMap<>();

                // Cargar propiedades por defecto
                Arrays.stream(entity.getClass().getDeclaredFields()).forEach(field -> {
                    field.setAccessible(true);
                    try {
                        row.put(field.getName(), field.get(entity));
                    } catch (IllegalAccessException ignored) {}
                });

                // Editar columnas existentes
                editedColumns.forEach((key, func) -> row.put(key, func.apply(entity)));

                // Añadir columnas nuevas
                addedColumns.forEach((key, func) -> row.put(key, func.apply(entity)));

                return row;
            }).collect(Collectors.toList());

        Map<String, Object> response = new HashMap<>();
        response.put("draw", draw);
        response.put("recordsTotal", page.getTotalElements());
        response.put("recordsFiltered", page.getTotalElements()); // cambia si aplicas filtro real
        response.put("data", data);

        return response;
    }
}
