import os
from urllib.parse import quote

from django import template
from django.urls import reverse
from django.utils.html import format_html
from django.utils.safestring import mark_safe

register = template.Library()

@register.filter
def urlencode_path(url):
    """
    URL-encode a file path for use in href attributes.
    Handles Unicode characters and special characters correctly.

    This filter properly encodes characters that Django's FileField.url
    might miss (like apostrophes) while not double-encoding already
    encoded characters.

    Usage: {{ attachment.file.url|urlencode_path }}
    """
    if not url:
        return ''

    from urllib.parse import urlsplit, urlunsplit, unquote

    # Parse the URL into components
    parsed = urlsplit(url)

    # Decode the path first (to handle any existing encoding)
    # then re-encode it properly
    decoded_path = unquote(parsed.path)

    # Quote the path, keeping only slashes safe
    # This will encode apostrophes, spaces, and Unicode characters
    encoded_path = quote(decoded_path, safe='/')

    # Reconstruct the URL with the properly encoded path
    return urlunsplit((parsed.scheme, parsed.netloc, encoded_path, parsed.query, parsed.fragment))


@register.filter
def filesize(file_path):
    """
    Get file size from a file path safely, handling Unicode filenames.
    Returns file size in bytes, suitable for piping to filesizeformat.

    This filter handles Unicode file paths correctly under Apache/WSGI
    by using proper encoding and bypassing Django's FileField.size
    which can fail with non-ASCII characters.

    Usage: {{ attachment.file.path|filesize|filesizeformat }}
    """
    try:
        if not file_path:
            return 0

        # Handle different encoding scenarios in Apache/WSGI
        if isinstance(file_path, bytes):
            # If it's bytes, keep as-is (already in filesystem encoding)
            path_bytes = file_path
        elif isinstance(file_path, str):
            # Fix UTF-8 mojibake: UTF-8 bytes incorrectly decoded as Latin-1
            # (common in Apache/WSGI with ASCII default encoding)
            try:
                # Try to encode back to bytes using Latin-1 (preserves byte values)
                # then decode properly as UTF-8 to get the correct string
                file_path = file_path.encode('latin-1').decode('utf-8')
            except (UnicodeDecodeError, UnicodeEncodeError):
                # If that fails, the path is already correctly decoded
                pass

            # Now encode to UTF-8 bytes for filesystem operations
            # Use UTF-8 explicitly instead of os.fsencode() which uses ASCII in Apache/WSGI
            path_bytes = file_path.encode('utf-8')
        else:
            return 0

        # Use byte paths for filesystem operations to avoid encoding issues
        if os.path.exists(path_bytes):
            return os.path.getsize(path_bytes)
    except (OSError, TypeError, UnicodeError, AttributeError) as e:
        # Log the error for debugging if needed
        import logging
        logging.warning(f"filesize filter error for path {repr(file_path) if 'file_path' in locals() else 'unknown'}: {e}")

    return 0
