"""Query layer for DMS assets — wraps storage models with DMS-scoped access."""

from __future__ import annotations

import uuid

from django.db.models import QuerySet

from simorgh.apps.dms.assets.constants import APP_CONTEXT
from simorgh.apps.dms.common.exceptions import AssetNotFound
from simorgh.apps.storage.models import FileMetadata, FileVariant, UploadSession


def get_asset(tenant_id: int, public_id: str) -> FileMetadata:
    """Return a non-deleted DMS FileMetadata record or raise AssetNotFound."""
    try:
        uid = uuid.UUID(str(public_id))
    except (ValueError, AttributeError) as exc:
        raise AssetNotFound(f"Invalid asset id: {public_id!r}") from exc

    try:
        return FileMetadata.objects.get(
            tenant_id=tenant_id,
            public_id=uid,
            app_context=APP_CONTEXT,
            is_deleted=False,
        )
    except FileMetadata.DoesNotExist as exc:
        raise AssetNotFound(f"File asset {public_id!r} not found.") from exc


def list_assets(
    tenant_id: int,
    *,
    upload_status: str | None = None,
    folder_id: str | None = None,
    content_type: str | None = None,
    search: str | None = None,
) -> QuerySet:
    """Return a QuerySet of active DMS file assets for the given tenant."""
    qs = FileMetadata.objects.filter(
        tenant_id=tenant_id,
        app_context=APP_CONTEXT,
        is_deleted=False,
    ).order_by("-created_at")

    if upload_status:
        qs = qs.filter(upload_status=upload_status)
    if folder_id:
        try:
            qs = qs.filter(folder_id=uuid.UUID(str(folder_id)))
        except (ValueError, AttributeError):
            pass
    if content_type:
        qs = qs.filter(content_type__icontains=content_type)
    if search:
        qs = qs.filter(filename__icontains=search)

    return qs


def list_variants(asset: FileMetadata) -> QuerySet:
    """Return all FileVariant records for the given asset."""
    return FileVariant.objects.filter(source=asset).order_by("kind")


def get_upload_session(tenant_id: int, public_id: str) -> UploadSession:
    """Return an UploadSession for the given tenant or raise AssetNotFound."""
    try:
        uid = uuid.UUID(str(public_id))
    except (ValueError, AttributeError) as exc:
        raise AssetNotFound(f"Invalid session id: {public_id!r}") from exc

    try:
        return UploadSession.objects.get(
            tenant_id=tenant_id,
            public_id=uid,
            app_context=APP_CONTEXT,
        )
    except UploadSession.DoesNotExist as exc:
        raise AssetNotFound(f"Upload session {public_id!r} not found.") from exc
