import json
from pathlib import Path

from django.contrib.auth import logout
from django.shortcuts import redirect
from django.utils import timezone

SESSION_LAST_ACTIVITY = "skv_last_activity"
DEFAULT_TIMEOUT_SECONDS = 15 * 60
MIN_TIMEOUT_SECONDS = 1
MAX_TIMEOUT_SECONDS = 8 * 60 * 60


def get_session_timeout_seconds():
    """Read the saved inactivity timeout; default safely to 15 minutes."""
    config_path = Path(__file__).resolve().parent.parent / "session_timeout.json"

    try:
        with config_path.open("r", encoding="utf-8") as config_file:
            config = json.load(config_file)

        # Backward compatibility with the existing {"minutes": 15} format.
        if "seconds_total" in config:
            total_seconds = int(config["seconds_total"])
        elif any(key in config for key in ("hours", "minutes", "seconds")):
            hours = int(config.get("hours", 0))
            minutes = int(config.get("minutes", 0))
            seconds = int(config.get("seconds", 0))
            if hours < 0 or not 0 <= minutes <= 59 or not 0 <= seconds <= 59:
                return DEFAULT_TIMEOUT_SECONDS
            total_seconds = hours * 3600 + minutes * 60 + seconds
        else:
            total_seconds = int(config.get("minutes", 15)) * 60

        if not MIN_TIMEOUT_SECONDS <= total_seconds <= MAX_TIMEOUT_SECONDS:
            return DEFAULT_TIMEOUT_SECONDS
        return total_seconds

    except (OSError, ValueError, TypeError, json.JSONDecodeError):
        return DEFAULT_TIMEOUT_SECONDS


class SessionSecurityMiddleware:
    """Expire inactive staff sessions without deleting business records."""

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

    def __call__(self, request):
        if request.user.is_authenticated and request.user.is_staff:
            now = timezone.now().timestamp()
            previous = request.session.get(SESSION_LAST_ACTIVITY)

            if previous is not None:
                try:
                    elapsed = now - float(previous)
                except (TypeError, ValueError):
                    elapsed = 0

                if elapsed >= get_session_timeout_seconds():
                    logout(request)
                    request.session.flush()
                    return redirect("/login/?timeout=1")

            request.session[SESSION_LAST_ACTIVITY] = now
            request.session.modified = True

        return self.get_response(request)
