import logging
import os
from functools import cache
from typing import Any, Dict

from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker

from ..web.services.settings_manager import SettingsManager, check_env_setting

logger = logging.getLogger(__name__)


# Database path.
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "data"))
DB_PATH = os.path.join(DATA_DIR, "ldr.db")


@cache
def get_db_session() -> Session:
    """
    Returns:
        The singleton DB session.
    """
    engine = create_engine(f"sqlite:///{DB_PATH}")
    session_class = sessionmaker(bind=engine)
    return session_class()


@cache
def get_settings_manager() -> SettingsManager:
    """
    Returns:
        The singleton settings manager.

    """
    return SettingsManager(db_session=get_db_session())


def get_db_setting(
    key: str, default_value: Any | None = None, check_env: bool = True
) -> str | Dict[str, Any] | None:
    """
    Get a setting from the database with fallback to default value

    Args:
        key: The setting key.
        default_value: If the setting is not found, it will return this instead.
        check_env: If true, it will check the corresponding environment
            variable before checking the DB and return that if it is set.

    """
    if check_env:
        env_value = check_env_setting(key)
        if env_value is not None:
            return env_value

    try:
        # Get settings manager which handles database access
        value = get_settings_manager().get_setting(key)

        if value is not None:
            return value
    except Exception as e:
        logger.error(f"Error getting setting {key} from database: {e}")

    logger.warning(f"Could not find setting '{key}' in the database.")
    return default_value
