AnalyticsControllerValidationHelper.java

package com.smartsupplypro.inventory.controller.analytics;

import java.time.LocalDate;
import java.time.LocalDateTime;

import org.springframework.stereotype.Component;

import com.smartsupplypro.inventory.dto.StockUpdateFilterDTO;
import com.smartsupplypro.inventory.exception.InvalidRequestException;

/**
 * Validation helper for analytics controller request parameters.
 *
 * <p>Centralizes validation logic for:
 * <ul>
 *   <li>Date range validation (start ≤ end)</li>
 *   <li>Non-blank string parameters</li>
 *   <li>Filter DTO validation (date ranges, numeric ranges)</li>
 *   <li>Default date window application (last 30 days)</li>
 * </ul>
 *
 * @author Smart Supply Pro Development Team
 * @version 1.0.0
 * @since 2.0.0
 */
@Component
public class AnalyticsControllerValidationHelper {

    /**
     * Validates LocalDate range parameters.
     *
     * @param start start date (must not be null)
     * @param end end date (must not be null and >= start)
     * @param startName parameter name for error messages
     * @param endName parameter name for error messages
     * @throws InvalidRequestException if validation fails
     */
    public void validateDateRange(LocalDate start, LocalDate end, String startName, String endName) {
        if (start == null || end == null) {
            throw new InvalidRequestException(startName + " and " + endName + " are required");
        }
        if (start.isAfter(end)) {
            throw new InvalidRequestException(startName + " must be on or before " + endName);
        }
    }

    /**
     * Validates LocalDateTime range parameters.
     *
     * @param start start datetime
     * @param end end datetime
     * @param startName parameter name for error messages
     * @param endName parameter name for error messages
     * @throws InvalidRequestException if start > end
     */
    public void validateDateTimeRange(LocalDateTime start, LocalDateTime end, String startName, String endName) {
        if (start != null && end != null && start.isAfter(end)) {
            throw new InvalidRequestException(startName + " must be on or before " + endName);
        }
    }

    /**
     * Validates string parameter is not blank.
     *
     * @param value parameter value to check
     * @param name parameter name for error messages
     * @throws InvalidRequestException if value is blank
     */
    public void requireNonBlank(String value, String name) {
        if (value == null || value.trim().isEmpty()) {
            throw new InvalidRequestException(name + " must not be blank");
        }
    }

    /**
     * Validates numeric range parameters.
     *
     * @param min minimum value
     * @param max maximum value
     * @param minName parameter name for error messages
     * @param maxName parameter name for error messages
     * @throws InvalidRequestException if min > max
     */
    public void validateNumericRange(Integer min, Integer max, String minName, String maxName) {
        if (min != null && max != null && min > max) {
            throw new InvalidRequestException(minName + " must be <= " + maxName);
        }
    }

    /**
     * Applies default date window (last 30 days) if both dates are null.
     *
     * @param startDate current start date (nullable)
     * @param endDate current end date (nullable)
     * @return array with [startDate, endDate] with defaults applied
     */
    public LocalDateTime[] applyDefaultDateWindow(LocalDateTime startDate, LocalDateTime endDate) {
        if (startDate == null && endDate == null) {
            endDate = LocalDateTime.now();
            startDate = endDate.minusDays(30);
        }
        return new LocalDateTime[]{startDate, endDate};
    }

    /**
     * Validates stock update filter DTO constraints.
     *
     * @param filter the filter DTO to validate
     * @throws InvalidRequestException if validation fails
     */
    public void validateStockUpdateFilter(StockUpdateFilterDTO filter) {
        validateDateTimeRange(filter.getStartDate(), filter.getEndDate(), "startDate", "endDate");
        validateNumericRange(filter.getMinChange(), filter.getMaxChange(), "minChange", "maxChange");
    }
}