"""Physical installation of .bsp map files onto the server (copy + compress)."""

import shutil
import time
from pathlib import Path
from typing import Any

from core import constants
from core.domain.validator import validate_bsp_file, validate_map_name
from core.exceptions import MapInstallerError
from core.io.compressor import compress_bsp
from core.logger_config import logger


def _verify_map_integrity(bsp_file: Path) -> None:
    """Validates the filename security and the integrity of the BSP structure."""
    if not validate_map_name(bsp_file.stem) or bsp_file.suffix.lower() != ".bsp":
        msg = f"Nom de map invalide (caractères non autorisés ou extension incorrecte) : {bsp_file.name}"
        raise MapInstallerError(msg)

    if not validate_bsp_file(bsp_file):
        msg = f"Fichier BSP corrompu ou invalide : {bsp_file}"
        raise MapInstallerError(msg)


def _handle_source_cleanup(bsp_file: Path, force_delete: bool) -> None:
    """Handles the secure deletion of the temporary source file if necessary."""
    if force_delete or constants.DELETE_TEMP_BSP_AFTER_INSTALL:
        try:
            if bsp_file.exists():
                bsp_file.unlink()
                logger.info(f"Temporary file cleanup complete : {bsp_file.name}")
        except OSError as e:
            logger.warning(f"Unable to delete the temporary file {bsp_file.name} : {e}")


def _calculate_compression_gain(source_size: int, compressed_file: Path) -> float:
    """Calculates the compression ratio achieved after bz2 compression."""
    if source_size == 0:
        return 0.0
    compressed_size = compressed_file.stat().st_size
    return round((1 - (compressed_size / source_size)) * 100, 2)


def install_map(bsp_file: str | Path, delete_source: bool = False) -> dict[str, Any]:
    """Supports the complete physical deployment of a card on the server."""
    bsp_file = Path(bsp_file)
    start_time = time.perf_counter()

    _verify_map_integrity(bsp_file)

    source_size = bsp_file.stat().st_size
    map_name = bsp_file.stem

    destination_bsp = constants.MAPS_FOLDER / bsp_file.name
    destination_bz2 = constants.DOWNLOAD_MAPS_FOLDER / f"{bsp_file.name}.bz2"

    logger.info(f"Installation of the '{map_name}' map has started")

    shutil.copy2(bsp_file, destination_bsp)
    compress_bsp(destination_bsp, destination_bz2)

    _handle_source_cleanup(bsp_file, force_delete=delete_source)

    elapsed = time.perf_counter() - start_time
    logger.info(f"Map '{map_name}' successfully installed in {elapsed:.3f}s")

    return {
        "success": True,
        "map_name": map_name,
        "source_file": str(bsp_file),
        "installed_bsp": str(destination_bsp),
        "installed_bz2": str(destination_bz2),
        "source_size": source_size,
        "compressed_size": destination_bz2.stat().st_size,
        "compression_ratio": _calculate_compression_gain(source_size, destination_bz2),
        "install_time_seconds": round(elapsed, 3),
    }


def is_map_installed(bsp_file: str | Path) -> bool:
    """Determines whether the map is present in both the game and on FastDL."""
    target_path = Path(bsp_file)
    destination_bsp = constants.MAPS_FOLDER / target_path.name
    destination_bz2 = constants.DOWNLOAD_MAPS_FOLDER / f"{target_path.name}.bz2"

    return destination_bsp.exists() and destination_bz2.exists()
