# File: cpp_python_debug/core/file_utils.py
import hashlib
import os
import logging
import re
from typing import Optional

logger = logging.getLogger(__name__)


def calculate_file_checksum(filepath: str, hash_type: str = "md5") -> Optional[str]:
    """
    Calculates the checksum (MD5) of a given file.
    """
    if not os.path.isfile(filepath):
        logger.warning(f"Checksum calculation: File not found at {filepath}")
        return None

    if hash_type != "md5":
        logger.error(f"Checksum calculation: Unsupported hash_type '{hash_type}'.")
        return None

    try:
        hasher = hashlib.md5()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(8192), b""):
                hasher.update(chunk)
        return hasher.hexdigest()
    except Exception as e:
        logger.error(f"Error calculating MD5 for {filepath}: {e}", exc_info=True)
        return None


def sanitize_filename_component(component: str, max_len: int = 50) -> str:
    """
    Sanitizes a string component to be safe for use in filenames.
    Replaces problematic characters, simplifies common patterns, and limits length.

    Args:
        component: The string to sanitize.
        max_len: The maximum allowed length for the sanitized component.

    Returns:
        A filesystem-safe string component.
    """
    if not component:
        return "unknown_component"

    # For breakpoint strings like "path/to/file.cpp:123", extract the filename and line.
    match = re.search(r"[/\\]([^/\\]+):(\d+)$", component)
    if match:
        component = f"{match.group(1)}_{match.group(2)}" # e.g., "file_cpp_123"

    # For variable strings like "var@dim1,dim2", use only the base variable name.
    component = component.split('@')[0]

    # Replace remaining problematic characters with underscores.
    # Adds '.' and ':' to the list to be safe, although some might have been handled above.
    sanitized = re.sub(r'[\\/*?:"<>|.,]', "_", component)

    # Replace spaces with a single underscore.
    sanitized = sanitized.replace(" ", "_")

    # Collapse multiple underscores into one.
    sanitized = re.sub(r"_+", "_", sanitized)

    # Remove leading/trailing underscores.
    sanitized = sanitized.strip("_")

    # Enforce maximum length.
    if len(sanitized) > max_len:
        sanitized = sanitized[:max_len]

    # If the process left an empty string, provide a fallback.
    if not sanitized:
        return "sanitized_empty"

    return sanitized