"""Warning calculation for the settings UI.

Thin orchestrator: reads settings from a single DB session,
delegates to pure check functions in hardware.py and context.py.
"""

from typing import List

from flask import session
from loguru import logger

from ...database.session_context import get_user_db_session
from ...utilities.db_utils import get_settings_manager
from .context import (
    check_context_below_history,
    check_context_truncation_history,
)
from .backup import (
    check_backup_disabled,
    check_backup_healthy,
    check_no_backups_exist,
)
from .hardware import (
    LOCAL_PROVIDERS,
    check_high_context,
    check_legacy_server_config,
    check_model_mismatch,
)


def _safe_check(check_fn, *args, **kwargs):
    """Run a single warning check, returning None on failure."""
    try:
        return check_fn(*args, **kwargs)
    except Exception:
        name = getattr(check_fn, "__name__", repr(check_fn))
        logger.exception(f"Warning check {name} failed")
        return None


def calculate_warnings() -> List[dict]:
    """Calculate current warning conditions based on settings.

    Uses a single DB session for all setting reads and history queries.
    """
    warnings: List[dict] = []

    try:
        username = session.get("username")
        with get_user_db_session(username) as db_session:
            if not db_session:
                return []

            settings_manager = get_settings_manager(db_session, username)

            # Read all needed settings in one session
            provider = settings_manager.get_setting(
                "llm.provider", "ollama"
            ).lower()
            local_context = settings_manager.get_setting(
                "llm.local_context_window_size", 4096
            )
            current_model = settings_manager.get_setting("llm.model", "")
            dismiss_high_context = settings_manager.get_setting(
                "app.warnings.dismiss_high_context", False
            )
            dismiss_model_mismatch = settings_manager.get_setting(
                "app.warnings.dismiss_model_mismatch", False
            )
            dismiss_context_warning = settings_manager.get_setting(
                "app.warnings.dismiss_context_reduced", False
            )
            dismiss_legacy_config = settings_manager.get_setting(
                "app.warnings.dismiss_legacy_config", False
            )
            backup_enabled = settings_manager.get_setting(
                "backup.enabled", True
            )
            dismiss_backup_disabled = settings_manager.get_setting(
                "app.warnings.dismiss_backup_disabled", False
            )
            dismiss_no_backups = settings_manager.get_setting(
                "app.warnings.dismiss_no_backups", False
            )

            logger.debug(f"Starting warning calculation - provider={provider}")

            is_local = provider in LOCAL_PROVIDERS

            # --- Hardware / settings checks (pure functions) ---
            w = _safe_check(
                check_high_context,
                provider,
                local_context,
                dismiss_high_context,
            )
            if w:
                warnings.append(w)

            w = _safe_check(
                check_model_mismatch,
                provider,
                current_model,
                local_context,
                dismiss_model_mismatch,
            )
            if w:
                warnings.append(w)

            w = _safe_check(check_legacy_server_config, dismiss_legacy_config)
            if w:
                warnings.append(w)

            # --- Backup checks ---
            w = _safe_check(
                check_backup_disabled, backup_enabled, dismiss_backup_disabled
            )
            if w:
                warnings.append(w)

            # Check backup file status (lightweight filesystem glob)
            dismiss_backup_info = settings_manager.get_setting(
                "app.warnings.dismiss_backup_info", False
            )
            try:
                from ...config.paths import get_user_backup_directory
                from ...utilities.formatting import human_size

                username = session.get("username")
                if username:
                    backup_dir = get_user_backup_directory(username)
                    total_size = 0
                    backup_count = 0
                    for f in backup_dir.glob("ldr_backup_*.db"):
                        try:
                            total_size += f.stat().st_size
                            backup_count += 1
                        except FileNotFoundError:
                            continue

                    w = _safe_check(
                        check_no_backups_exist,
                        backup_enabled,
                        backup_count,
                        dismiss_no_backups,
                    )
                    if w:
                        warnings.append(w)

                    w = _safe_check(
                        check_backup_healthy,
                        backup_enabled,
                        backup_count,
                        human_size(total_size),
                        dismiss_backup_info,
                    )
                    if w:
                        warnings.append(w)
            except Exception:
                logger.debug("Backup status check skipped")

            # --- History-based checks (need DB queries) ---
            if is_local and not dismiss_context_warning:
                w = _safe_check(
                    check_context_below_history, db_session, local_context
                )
                if w:
                    warnings.append(w)

                w = _safe_check(
                    check_context_truncation_history, db_session, local_context
                )
                if w:
                    warnings.append(w)

    except Exception:
        logger.exception("Error calculating warnings")

    return warnings
