package org.raddatz.familienarchiv.document;

import org.raddatz.familienarchiv.exception.DomainException;
import org.raddatz.familienarchiv.exception.ErrorCode;

import java.time.LocalDate;

/**
 * Cross-field validation and normalization shared by every domain that stores a
 * {@link LocalDate} + {@link DatePrecision} pair — a person's life dates (ADR-039 / V76)
 * and a relationship's from/to dates (ADR-044 / V78). Kept out of {@link DatePrecision}
 * itself because that enum is a frozen contract mirror of the import normalizer (ADR-025)
 * and must carry no behaviour.
 */
public final class DatePrecisionValidation {

    private DatePrecisionValidation() {}

    /**
     * Enforces the date ⇔ precision coherence the V76/V78 CHECK constraints also enforce:
     * a date requires a non-{@code UNKNOWN} precision, and a non-{@code UNKNOWN} precision
     * requires a date. Validated in-service so the caller gets a structured 400 instead of
     * the database constraint's raw 500.
     *
     * @param side human-readable field label woven into the error message ("birth", "from", …)
     */
    public static void requireCoherence(LocalDate date, DatePrecision precision, String side) {
        if (date != null && (precision == null || precision == DatePrecision.UNKNOWN)) {
            throw DomainException.badRequest(ErrorCode.INVALID_DATE_PRECISION,
                    side + " date is set but its precision is missing or UNKNOWN");
        }
        if (date == null && precision != null && precision != DatePrecision.UNKNOWN) {
            throw DomainException.badRequest(ErrorCode.INVALID_DATE_PRECISION,
                    side + " date precision " + precision + " is set without a date");
        }
    }

    /** A null precision means "no precision recorded" → {@link DatePrecision#UNKNOWN}. */
    public static DatePrecision normalize(DatePrecision precision) {
        return precision == null ? DatePrecision.UNKNOWN : precision;
    }
}
