#!/usr/bin/env bash
# gniza4cp/lib/config.sh — Shell-variable config loading & validation

# Safe config parser — reads KEY=VALUE lines without executing arbitrary code.
# Only processes lines matching ^[A-Z_][A-Z_0-9]*= and strips surrounding quotes.
_safe_source_config() {
    local filepath="$1"
    local line key value
    while IFS= read -r line || [[ -n "$line" ]]; do
        # Skip blank lines and comments
        [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
        # Match KEY=VALUE (optional quotes)
        if [[ "$line" =~ ^([A-Z_][A-Z_0-9]*)=(.*) ]]; then
            key="${BASH_REMATCH[1]}"
            value="${BASH_REMATCH[2]}"
            # Strip surrounding double or single quotes
            if [[ "$value" =~ ^\"(.*)\"$ ]]; then
                value="${BASH_REMATCH[1]}"
            elif [[ "$value" =~ ^\'(.*)\'$ ]]; then
                value="${BASH_REMATCH[1]}"
            fi
            declare -g "$key=$value"
        fi
    done < "$filepath"
}

load_config() {
    local config_file="${1:-$DEFAULT_CONFIG_FILE}"

    if [[ ! -f "$config_file" ]]; then
        die "Config file not found: $config_file (create via WHM or copy gniza4cp.conf.example)"
    fi

    # Parse the config (safe key=value reader, no code execution)
    _safe_source_config "$config_file" || die "Failed to parse config file: $config_file"

    # Apply defaults for optional settings
    TEMP_DIR="${TEMP_DIR:-$DEFAULT_TEMP_DIR}"
    INCLUDE_ACCOUNTS="${INCLUDE_ACCOUNTS:-}"
    EXCLUDE_ACCOUNTS="${EXCLUDE_ACCOUNTS:-$DEFAULT_EXCLUDE_ACCOUNTS}"
    LOG_DIR="${LOG_DIR:-$DEFAULT_LOG_DIR}"
    LOG_LEVEL="${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}"
    LOG_RETAIN="${LOG_RETAIN:-$DEFAULT_LOG_RETAIN}"
    NOTIFY_EMAIL="${NOTIFY_EMAIL:-}"
    NOTIFY_ON="${NOTIFY_ON:-$DEFAULT_NOTIFY_ON}"
    SMTP_HOST="${SMTP_HOST:-}"
    SMTP_PORT="${SMTP_PORT:-$DEFAULT_SMTP_PORT}"
    SMTP_USER="${SMTP_USER:-}"
    SMTP_PASSWORD="${SMTP_PASSWORD:-}"
    SMTP_FROM="${SMTP_FROM:-}"
    SMTP_SECURITY="${SMTP_SECURITY:-$DEFAULT_SMTP_SECURITY}"
    LOCK_FILE="${LOCK_FILE:-$DEFAULT_LOCK_FILE}"
    SSH_TIMEOUT="${SSH_TIMEOUT:-$DEFAULT_SSH_TIMEOUT}"
    SSH_RETRIES="${SSH_RETRIES:-$DEFAULT_SSH_RETRIES}"
    RSYNC_EXTRA_OPTS="${RSYNC_EXTRA_OPTS:-}"
    USER_RESTORE_REMOTES="${USER_RESTORE_REMOTES:-$DEFAULT_USER_RESTORE_REMOTES}"

    # --debug flag overrides config
    [[ "${GNIZA4CP_DEBUG:-false}" == "true" ]] && LOG_LEVEL="debug"

    export TEMP_DIR INCLUDE_ACCOUNTS EXCLUDE_ACCOUNTS BWLIMIT RETENTION_COUNT
    export LOG_DIR LOG_LEVEL LOG_RETAIN NOTIFY_EMAIL NOTIFY_ON
    export SMTP_HOST SMTP_PORT SMTP_USER SMTP_PASSWORD SMTP_FROM SMTP_SECURITY
    export LOCK_FILE SSH_TIMEOUT SSH_RETRIES RSYNC_EXTRA_OPTS USER_RESTORE_REMOTES
}

validate_config() {
    local errors=0

    # Per-remote validation is handled by validate_remote() in remotes.sh.
    # Here we only validate local/global settings.

    case "$NOTIFY_ON" in
        always|failure|never) ;;
        *) log_error "NOTIFY_ON must be always|failure|never, got: $NOTIFY_ON"; ((errors++)) || true ;;
    esac

    case "$LOG_LEVEL" in
        debug|info|warn|error) ;;
        *) log_error "LOG_LEVEL must be debug|info|warn|error, got: $LOG_LEVEL"; ((errors++)) || true ;;
    esac

    # SMTP validation (only when SMTP_HOST is set)
    if [[ -n "${SMTP_HOST:-}" ]]; then
        case "$SMTP_SECURITY" in
            tls|ssl|none) ;;
            *) log_error "SMTP_SECURITY must be tls|ssl|none, got: $SMTP_SECURITY"; ((errors++)) || true ;;
        esac

        if [[ -n "${SMTP_PORT:-}" ]] && { [[ ! "$SMTP_PORT" =~ ^[0-9]+$ ]] || (( SMTP_PORT < 1 || SMTP_PORT > 65535 )); }; then
            log_error "SMTP_PORT must be 1-65535, got: $SMTP_PORT"
            ((errors++)) || true
        fi
    fi

    # Validate numeric fields
    if [[ -n "${SSH_TIMEOUT:-}" ]] && [[ ! "$SSH_TIMEOUT" =~ ^[0-9]+$ ]]; then
        log_error "SSH_TIMEOUT must be a non-negative integer, got: $SSH_TIMEOUT"
        ((errors++)) || true
    fi

    if [[ -n "${SSH_RETRIES:-}" ]] && [[ ! "$SSH_RETRIES" =~ ^[0-9]+$ ]]; then
        log_error "SSH_RETRIES must be a non-negative integer, got: $SSH_RETRIES"
        ((errors++)) || true
    fi

    if [[ -n "${LOG_RETAIN:-}" ]] && [[ ! "$LOG_RETAIN" =~ ^[0-9]+$ ]]; then
        log_error "LOG_RETAIN must be a non-negative integer, got: $LOG_RETAIN"
        ((errors++)) || true
    fi

    # Validate RSYNC_EXTRA_OPTS characters (prevent flag injection)
    if [[ -n "${RSYNC_EXTRA_OPTS:-}" ]] && [[ ! "$RSYNC_EXTRA_OPTS" =~ ^[a-zA-Z0-9\ ._=/,-]+$ ]]; then
        log_error "RSYNC_EXTRA_OPTS contains invalid characters: $RSYNC_EXTRA_OPTS"
        ((errors++)) || true
    fi

    if (( errors > 0 )); then
        log_error "Configuration has $errors error(s)"
        return 1
    fi
    return 0
}
