package com.banesco.common.infraestructure.utils;

import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * Clase para validación de fechas con configuración flexible. Permite validar
 * fechas en diferentes formatos, comprobar rangos de años y verificar la
 * correcta formación de componentes de fecha (año, mes, día). Implementa el
 * patrón Builder para facilitar la configuración personalizada de los
 * parámetros de validación.
 */
public class DateValidator {

    private final DateTimeFormatter dateFormatter;
    private final PatternValidator datePattern;
    private final int minYear;
    private final int maxYear;

    private DateValidator(Builder builder) {
        this.dateFormatter = builder.dateFormatter;
        this.datePattern = new PatternValidator(builder.dateFormatRegex);
        this.minYear = builder.minYear;
        this.maxYear = builder.maxYear;
    }

    public static class Builder {

        private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        private String dateFormatRegex = "(\\d{4})/(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])";
        private int minYear = 1900;
        private int maxYear = 2100;

        public Builder withDateFormatter(String dateFormatterPattern) {
            this.dateFormatter = DateTimeFormatter.ofPattern(dateFormatterPattern);
            return this;
        }

        public Builder withDateFormatRegex(String dateFormatRegex) {
            this.dateFormatRegex = dateFormatRegex;
            return this;
        }

        public Builder withMinYear(int minYear) {
            this.minYear = minYear;
            return this;
        }

        public Builder withMaxYear(int maxYear) {
            this.maxYear = maxYear;
            return this;
        }

        public DateValidator build() {
            return new DateValidator(this);
        }
    }

    public boolean isValidDateFormat(String date) {
        return datePattern.isValid(date);
    }

    public boolean isValidDate(String date) {
        if (!isValidDateFormat(date)) {
            return false;
        }

        try {
            LocalDate parsedDate = LocalDate.parse(date, dateFormatter);
            String formattedDate = parsedDate.format(dateFormatter);
            return date.equals(formattedDate);
        } catch (DateTimeException e) {
            return false;
        }
    }

    public boolean isValidDate(int year, int month, int day) {
        return year >= minYear && year <= maxYear && month >= 1 && month <= 12 && isValidDayOfMonth(year, month, day);
    }

    private boolean isValidDayOfMonth(int year, int month, int day) {
        try {
            LocalDate.of(year, month, day);
            return true;
        } catch (DateTimeException e) {
            return false;
        }
    }
}
