package org.raddatz.familienarchiv.exception;

import org.springframework.http.HttpStatus;

/**
 * Exception for domain-level errors that should be surfaced to the API caller
 * with a machine-readable ErrorCode and an English developer message.
 */
public class DomainException extends RuntimeException {

    private final ErrorCode code;
    private final HttpStatus status;
    /** Seconds until the rate-limit window resets; {@code null} when not applicable. */
    private final Long retryAfterSeconds;

    public DomainException(ErrorCode code, HttpStatus status, String developerMessage) {
        super(developerMessage);
        this.code = code;
        this.status = status;
        this.retryAfterSeconds = null;
    }

    private DomainException(ErrorCode code, HttpStatus status, String developerMessage, Long retryAfterSeconds) {
        super(developerMessage);
        this.code = code;
        this.status = status;
        this.retryAfterSeconds = retryAfterSeconds;
    }

    public ErrorCode getCode() {
        return code;
    }

    public HttpStatus getStatus() {
        return status;
    }

    /** Returns the {@code Retry-After} value in seconds, or {@code null} if not set. */
    public Long getRetryAfterSeconds() {
        return retryAfterSeconds;
    }

    // --- Static factories for common cases ---

    public static DomainException notFound(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.NOT_FOUND, message);
    }

    public static DomainException forbidden(String message) {
        return new DomainException(ErrorCode.FORBIDDEN, HttpStatus.FORBIDDEN, message);
    }

    public static DomainException unauthorized(String message) {
        return new DomainException(ErrorCode.UNAUTHORIZED, HttpStatus.UNAUTHORIZED, message);
    }

    public static DomainException invalidCredentials() {
        return new DomainException(ErrorCode.INVALID_CREDENTIALS, HttpStatus.UNAUTHORIZED,
                "Invalid email or password");
    }

    public static DomainException conflict(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.CONFLICT, message);
    }

    public static DomainException badRequest(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.BAD_REQUEST, message);
    }

    public static DomainException internal(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.INTERNAL_SERVER_ERROR, message);
    }

    public static DomainException tooManyRequests(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.TOO_MANY_REQUESTS, message);
    }

    public static DomainException tooManyRequests(ErrorCode code, String message, long retryAfterSeconds) {
        return new DomainException(code, HttpStatus.TOO_MANY_REQUESTS, message, retryAfterSeconds);
    }

    public static DomainException serviceUnavailable(ErrorCode code, String message) {
        return new DomainException(code, HttpStatus.SERVICE_UNAVAILABLE, message);
    }
}
