"""DMS cache utilities.

Key builders
------------
All keys are tenant-scoped to prevent cross-tenant leakage.  Key patterns::

    dms:doc:{tenant_id}:{doc_id}
    dms:search:{tenant_id}:{params_hash}
    dms:folders:{tenant_id}:{repo_id}:root
    dms:folders:{tenant_id}:{folder_id}:children

TTL constants (seconds)
-----------------------
    DOCUMENT_DETAIL_TTL  = 300   (5 min)
    SEARCH_TTL           = 60    (1 min)
    FOLDER_TREE_TTL      = 600   (10 min)

Invalidation helpers
--------------------
    invalidate_document(tenant_id, doc_id)
    invalidate_repo_folders(tenant_id, repo_id)
    invalidate_folder_children(tenant_id, folder_id)
"""

from __future__ import annotations

import hashlib
import json
from typing import Any

# ---------------------------------------------------------------------------
# TTL constants
# ---------------------------------------------------------------------------

DOCUMENT_DETAIL_TTL: int = 300    # 5 minutes
SEARCH_TTL: int = 60               # 1 minute
FOLDER_TREE_TTL: int = 600         # 10 minutes


# ---------------------------------------------------------------------------
# Key builders
# ---------------------------------------------------------------------------

def document_detail_key(tenant_id: int, doc_id: str) -> str:
    """Cache key for a single document detail response."""
    return f"dms:doc:{tenant_id}:{doc_id}"


def search_results_key(tenant_id: int, params: dict[str, Any]) -> str:
    """Cache key for a search results response.

    ``params`` should be the validated query-param dict so that the same
    logical query always maps to the same cache key regardless of request
    argument ordering.
    """
    serialised = json.dumps(params, sort_keys=True, default=str)
    params_hash = hashlib.md5(serialised.encode(), usedforsecurity=False).hexdigest()
    return f"dms:search:{tenant_id}:{params_hash}"


def folder_tree_key(tenant_id: int, repo_id: str) -> str:
    """Cache key for the root folder list of a repository."""
    return f"dms:folders:{tenant_id}:{repo_id}:root"


def folder_children_key(tenant_id: int, folder_id: str) -> str:
    """Cache key for the direct children of a folder."""
    return f"dms:folders:{tenant_id}:{folder_id}:children"


# ---------------------------------------------------------------------------
# Invalidation helpers
# ---------------------------------------------------------------------------

def invalidate_document(tenant_id: int, doc_id: str) -> None:
    """Delete the cached document detail entry."""
    from django.core.cache import cache

    cache.delete(document_detail_key(tenant_id, doc_id))


def invalidate_repo_folders(tenant_id: int, repo_id: str) -> None:
    """Delete the cached root folder list for a repository."""
    from django.core.cache import cache

    cache.delete(folder_tree_key(tenant_id, repo_id))


def invalidate_folder_children(tenant_id: int, folder_id: str) -> None:
    """Delete the cached children list for a folder."""
    from django.core.cache import cache

    cache.delete(folder_children_key(tenant_id, folder_id))
