import threading

_thread_locals = threading.local()


def get_current_user():
    return getattr(_thread_locals, "user", None)


def get_current_request():
    return getattr(_thread_locals, "request", None)


class CurrentUserMiddleware:
    """Stashes the logged-in user + request on a thread-local so that model
    signal handlers (which don't receive the request) can still know who
    made a change. This is what powers the Audit Trail."""

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        _thread_locals.user = getattr(request, "user", None)
        _thread_locals.request = request
        try:
            response = self.get_response(request)
        finally:
            _thread_locals.user = None
            _thread_locals.request = None
        return response


class TenantRoutingMiddleware:
    """Resolves which company database the current request should use,
    based on the logged-in user's active company, and activates that
    database for the duration of the request. This is what makes each
    company's dedicated database actually get used, instead of every
    company's data silently landing in the shared platform database.
    Must run after AuthenticationMiddleware (needs request.user) and
    SessionMiddleware (needs the session)."""

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Imported here, not at module load time, so the app registry is
        # guaranteed to be fully ready first.
        from core.db_router import (
            clear_current_tenant_alias,
            ensure_tenant_connection,
            set_current_tenant_alias,
        )
        from core.project_utils import get_current_project

        clear_current_tenant_alias()
        user = getattr(request, "user", None)
        if user is not None and getattr(user, "is_authenticated", False):
            project = get_current_project(request)
            if project is not None and project.is_active:
                alias = ensure_tenant_connection(project)
                if alias:
                    set_current_tenant_alias(alias)

        try:
            response = self.get_response(request)
        finally:
            clear_current_tenant_alias()
        return response
