import os
from datetime import timedelta
from dash import Dash
import dash_bootstrap_components as dbc
from flask_session import Session

from bfabric_web_apps.utils.config import settings


def _configure_flask_session(flask_app):
    """
    Configure Flask-Session on the Flask server.

    Supports filesystem (default) and Redis backends.
    Redis backend is used when SESSION_TYPE='redis' and Redis is available.

    Args:
        flask_app: The Flask application instance (from Dash app.server)
    """
    flask_app.config['SECRET_KEY'] = settings.SECRET_KEY
    flask_app.config['SESSION_TYPE'] = settings.SESSION_TYPE
    flask_app.config['SESSION_PERMANENT'] = settings.SESSION_PERMANENT
    flask_app.config['SESSION_USE_SIGNER'] = settings.SESSION_USE_SIGNER
    flask_app.config['SESSION_KEY_PREFIX'] = settings.SESSION_KEY_PREFIX
    flask_app.config['SESSION_COOKIE_SECURE'] = settings.SESSION_COOKIE_SECURE
    flask_app.config['SESSION_COOKIE_HTTPONLY'] = settings.SESSION_COOKIE_HTTPONLY
    flask_app.config['SESSION_COOKIE_SAMESITE'] = settings.SESSION_COOKIE_SAMESITE
    flask_app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(
        seconds=settings.PERMANENT_SESSION_LIFETIME
    )

    if settings.SESSION_TYPE == "redis":
        from bfabric_web_apps.utils.redis_connection import redis_conn
        flask_app.config['SESSION_REDIS'] = redis_conn
    else:
        # Filesystem backend
        flask_app.config['SESSION_FILE_DIR'] = settings.SESSION_FILE_DIR
        os.makedirs(settings.SESSION_FILE_DIR, exist_ok=True)

    Session(flask_app)


def create_app(title=None, url_base_pathname=None, assets_folder='assets'):
    """
    Initialize and return a Dash app instance.

    Args:
        title (str, optional): The browser tab title.
            Defaults to APP_TITLE from .env settings.
        url_base_pathname (str, optional): The base pathname for the app (e.g., '/lfu/').
            If not provided, reads from SCRIPT_NAME environment variable.
            Must start and end with '/'.
        assets_folder (str, optional): Path to assets folder.
            Defaults to 'assets' relative to caller.

    Returns:
        Dash: Configured Dash application instance.
    """
    # Get URL base pathname from parameter, settings, or environment variable
    if url_base_pathname is None:
        # Try settings first (from .env), then fall back to environment variable
        script_name = settings.SCRIPT_NAME or os.getenv('SCRIPT_NAME', '')
        if script_name:
            url_base_pathname = script_name if script_name.endswith('/') else script_name + '/'

    # Prepare Dash kwargs
    dash_kwargs = {
        'title': title or settings.APP_TITLE,
        'suppress_callback_exceptions': True,  # Allow dynamic callbacks
        'external_stylesheets': [dbc.themes.BOOTSTRAP],
        'meta_tags': [{"name": "viewport", "content": "width=device-width, initial-scale=1.0"}],
        'assets_folder': assets_folder,
    }

    # Add URL prefix if specified
    if url_base_pathname:
        dash_kwargs['requests_pathname_prefix'] = url_base_pathname
        dash_kwargs['routes_pathname_prefix'] = url_base_pathname

    app = Dash(__name__, **dash_kwargs)

    # Configure Flask-Session on the underlying Flask server
    _configure_flask_session(app.server)

    # Register session management routes
    from bfabric_web_apps.utils.session_routes import session_bp
    prefix = url_base_pathname.rstrip('/') if url_base_pathname else ''
    app.server.register_blueprint(session_bp, url_prefix=prefix)

    # Auto-extend session on every request (keeps session alive while user is active)
    from bfabric_web_apps.utils.session_utils import touch_session

    @app.server.before_request
    def extend_session_on_activity():
        """Extend session lifetime on each request."""
        touch_session()

    return app
