import logging
from typing import Any, Dict, Optional, Union

from ..database.models import Setting
from .settings_manager import SettingsManager

# Initialize logger
logger = logging.getLogger(__name__)


def get_settings_manager(db_session=None):
    """
    Get or create the settings manager instance.

    Args:
        db_session: Optional database session to use

    Returns:
        SettingsManager: The settings manager instance
    """
    return SettingsManager.get_instance(db_session)


def get_setting(key: str, default: Any = None, db_session=None) -> Any:
    """
    Get a setting value by key

    Args:
        key: Setting key
        default: Default value if setting not found
        db_session: Optional database session to use

    Returns:
        Any: The setting value
    """
    manager = get_settings_manager(db_session)
    return manager.get_setting(key, default)


def set_setting(key: str, value: Any, commit: bool = True, db_session=None) -> bool:
    """
    Set a setting value

    Args:
        key: Setting key
        value: Setting value
        commit: Whether to commit the change
        db_session: Optional database session

    Returns:
        bool: True if successful
    """
    manager = get_settings_manager(db_session)
    return manager.set_setting(key, value, commit)


def get_all_settings(db_session=None) -> Dict[str, Any]:
    """
    Get all settings, optionally filtered by type

    Args:
        db_session: Optional database session

    Returns:
        Dict[str, Any]: Dictionary of settings
    """
    manager = get_settings_manager(db_session)
    return manager.get_all_settings()


def create_or_update_setting(
    setting: Union[Dict[str, Any], Setting], commit: bool = True, db_session=None
) -> Optional[Setting]:
    """
    Create or update a setting

    Args:
        setting: Setting dictionary or object
        commit: Whether to commit the change
        db_session: Optional database session

    Returns:
        Optional[Setting]: The setting object if successful
    """
    manager = get_settings_manager(db_session)
    return manager.create_or_update_setting(setting, commit)


def bulk_update_settings(
    settings_dict: Dict[str, Any], commit: bool = True, db_session=None
) -> bool:
    """
    Update multiple settings from a dictionary

    Args:
        settings_dict: Dictionary of setting keys and values
        commit: Whether to commit the changes
        db_session: Optional database session

    Returns:
        bool: True if all updates were successful
    """
    manager = get_settings_manager(db_session)
    success = True

    for key, value in settings_dict.items():
        if not manager.set_setting(key, value, commit=False):
            success = False

    if commit and success and manager.db_session:
        try:
            manager.db_session.commit()
        except Exception as e:
            logger.error(f"Error committing bulk settings update: {e}")
            manager.db_session.rollback()
            success = False

    return success


def validate_setting(setting: Setting, value: Any) -> tuple[bool, Optional[str]]:
    """
    Validate a setting value based on its type and constraints

    Args:
        setting: The Setting object to validate against
        value: The value to validate

    Returns:
        tuple[bool, Optional[str]]: (is_valid, error_message)
    """
    from ..routes.settings_routes import validate_setting as routes_validate_setting

    return routes_validate_setting(setting, value)
