defmodule Mv.Config do @moduledoc """ Configuration helper functions for the application. Provides centralized access to configuration values to avoid magic strings/atoms scattered throughout the codebase. """ @doc """ Returns whether SQL sandbox mode is enabled. SQL sandbox mode is typically enabled in test environments to allow concurrent database access in tests. ## Returns - `true` if SQL sandbox is enabled - `false` otherwise """ @spec sql_sandbox?() :: boolean() def sql_sandbox? do Application.get_env(:mv, :sql_sandbox, false) end @doc """ Returns the maximum file size for CSV imports in bytes. Reads the `max_file_size_mb` value from the CSV import configuration and converts it to bytes. ## Returns - Maximum file size in bytes (default: 10_485_760 bytes = 10 MB) ## Examples iex> Mv.Config.csv_import_max_file_size_bytes() 10_485_760 """ @spec csv_import_max_file_size_bytes() :: non_neg_integer() def csv_import_max_file_size_bytes do max_file_size_mb = get_csv_import_config(:max_file_size_mb, 10) max_file_size_mb * 1024 * 1024 end @doc """ Returns the maximum number of rows allowed in CSV imports. Reads the `max_rows` value from the CSV import configuration. ## Returns - Maximum number of rows (default: 1000) ## Examples iex> Mv.Config.csv_import_max_rows() 1000 """ @spec csv_import_max_rows() :: pos_integer() def csv_import_max_rows do get_csv_import_config(:max_rows, 1000) end @doc """ Returns the maximum file size for CSV imports in megabytes. Reads the `max_file_size_mb` value from the CSV import configuration. ## Returns - Maximum file size in megabytes (default: 10) ## Examples iex> Mv.Config.csv_import_max_file_size_mb() 10 """ @spec csv_import_max_file_size_mb() :: pos_integer() def csv_import_max_file_size_mb do get_csv_import_config(:max_file_size_mb, 10) end # Helper function to get CSV import config values defp get_csv_import_config(key, default) do Application.get_env(:mv, :csv_import, []) |> Keyword.get(key, default) |> parse_and_validate_integer(default) end # Parses and validates integer configuration values. # # Accepts: # - Integer values (passed through) # - String integers (e.g., "1000") - parsed to integer # - Invalid values (e.g., "abc", nil) - falls back to default # # Always clamps the result to a minimum of 1 to ensure positive values. # # Note: We don't log warnings for unparseable values because: # - These functions may be called frequently (e.g., on every request) # - Logging would create excessive log spam # - The fallback to default provides a safe behavior # - Configuration errors should be caught during deployment/testing defp parse_and_validate_integer(value, _default) when is_integer(value) do max(1, value) end defp parse_and_validate_integer(value, default) when is_binary(value) do case Integer.parse(value) do {int, _remainder} -> max(1, int) :error -> default end end defp parse_and_validate_integer(_value, default) do default end end