from typing import Any, Dict, Optional, Union

from loguru import logger

from ...database.models import Setting
from ...utilities.db_utils import get_settings_manager


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() -> Dict[str, Any]:
    """
    Get all settings, optionally filtered by type

    Returns:
        Dict[str, Any]: Dictionary of settings

    """
    manager = get_settings_manager()
    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()
            # Emit WebSocket event for all changed settings
            manager._emit_settings_changed(list(settings_dict.keys()))
        except Exception:
            logger.exception("Error committing bulk settings update")
            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)
