"""
Files event listener.

Handles asynchronous physical file removal:

  file.deleted → delete the physical file from S3 or local filesystem
"""

import logging
from typing import Any

from src.events.base import BaseEvent
from src.events.dispatcher import on_event_async

logger = logging.getLogger(__name__)


def _is_valid_s3_key(s3_key: str) -> bool:
    """Basic validation that the s3_key looks like a legitimate upload path."""
    if not s3_key or len(s3_key) > 1024:
        return False
    # Prevent path traversal
    if ".." in s3_key or s3_key.startswith("/"):
        return False
    return True


@on_event_async("file.deleted")
async def purge_physical_file(event: BaseEvent) -> None:
    """
    Delete the physical file from S3 or the local filesystem asynchronously.

    On failure, logs the error.  The dispatcher retry mechanism and DLQ
    handle re-enqueue — this handler must NOT raise so that retries work
    correctly.
    """
    from src.apps.files.helper.io import remove_file_single

    data: Any = event.data
    file_id = data.get("file_id")
    upload_path = data.get("upload_path")

    if not upload_path:
        logger.warning(
            "purge_physical_file: no upload_path in event data for file_id=%s", file_id
        )
        return

    if not _is_valid_s3_key(upload_path):
        logger.error(
            "purge_physical_file: refusing to delete file with invalid upload_path for file_id=%s",
            file_id,
        )
        return

    try:
        remove_file_single(path=upload_path)
        logger.info(
            "purge_physical_file: physical file deleted for file_id=%s path=%s",
            file_id,
            upload_path,
        )
    except Exception as exc:
        logger.error(
            "purge_physical_file: failed to delete physical file for file_id=%s path=%s: %s",
            file_id,
            upload_path,
            exc,
        )
        # Do not raise — dispatcher retry + DLQ handles re-enqueue
