"""
File Organizer - Organize uploads by hostname
"""

import os
import re
from pathlib import Path
from typing import Tuple


def sanitize_hostname(hostname: str) -> str:
    """
    Sanitize hostname for use as directory name

    Args:
        hostname: The hostname to sanitize

    Returns:
        Sanitized hostname safe for use as directory name
    """
    # Remove invalid characters
    sanitized = re.sub(r'[^\w\-.]', '_', hostname)
    # Remove leading/trailing dots and underscores
    sanitized = sanitized.strip('._')
    # Replace multiple underscores with single
    sanitized = re.sub(r'_+', '_', sanitized)
    # Limit length
    sanitized = sanitized[:100]
    # Default if empty
    return sanitized if sanitized else 'unknown'


def get_device_upload_paths(base_upload_dir: str, hostname: str) -> Tuple[str, str]:
    """
    Get organized upload paths for a device

    Args:
        base_upload_dir: Base upload directory (e.g., "./uploads")
        hostname: Device hostname

    Returns:
        Tuple of (images_path, files_path)
    """
    sanitized_hostname = sanitize_hostname(hostname)

    images_path = os.path.join(base_upload_dir, sanitized_hostname, "images")
    files_path = os.path.join(base_upload_dir, sanitized_hostname, "files")

    return images_path, files_path


def ensure_device_directories(base_upload_dir: str, hostname: str) -> Tuple[str, str]:
    """
    Ensure device upload directories exist

    Args:
        base_upload_dir: Base upload directory
        hostname: Device hostname

    Returns:
        Tuple of (images_path, files_path)
    """
    images_path, files_path = get_device_upload_paths(base_upload_dir, hostname)

    # Create directories if they don't exist
    Path(images_path).mkdir(parents=True, exist_ok=True)
    Path(files_path).mkdir(parents=True, exist_ok=True)

    return images_path, files_path


def get_upload_path(base_upload_dir: str, hostname: str, is_image: bool, filename: str) -> str:
    """
    Get the full upload path for a file

    Args:
        base_upload_dir: Base upload directory
        hostname: Device hostname
        is_image: True if file is an image, False for documents
        filename: The filename to store

    Returns:
        Full path where file should be stored
    """
    images_path, files_path = ensure_device_directories(base_upload_dir, hostname)

    target_dir = images_path if is_image else files_path

    return os.path.join(target_dir, filename)


def is_image_file(filename: str, mime_type: str = None) -> bool:
    """
    Check if a file is an image based on extension and/or mime type

    Args:
        filename: The filename
        mime_type: Optional MIME type

    Returns:
        True if file is an image
    """
    # Check extension
    image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'}
    ext = os.path.splitext(filename)[1].lower()

    if ext in image_extensions:
        return True

    # Check MIME type if provided
    if mime_type and mime_type.startswith('image/'):
        return True

    return False


def migrate_existing_files(base_upload_dir: str, hostname: str, file_list: list) -> dict:
    """
    Migrate existing files to new organized structure

    Args:
        base_upload_dir: Base upload directory
        hostname: Device hostname
        file_list: List of tuples (filename, is_image)

    Returns:
        Dictionary mapping old paths to new paths
    """
    images_path, files_path = ensure_device_directories(base_upload_dir, hostname)

    migrations = {}

    for filename, is_image in file_list:
        old_path = os.path.join(base_upload_dir, filename)

        if is_image:
            new_path = os.path.join(images_path, filename)
        else:
            new_path = os.path.join(files_path, filename)

        migrations[old_path] = new_path

    return migrations


def get_relative_path(full_path: str, base_upload_dir: str) -> str:
    """
    Get relative path from base upload directory

    Args:
        full_path: Full file path
        base_upload_dir: Base upload directory

    Returns:
        Relative path from base directory
    """
    return os.path.relpath(full_path, base_upload_dir)
