"""Loader implementation for Mira archives."""

from __future__ import annotations

import importlib.abc
import importlib.machinery
import importlib.util
import marshal
import os

from mira.runtime.registry import MiraPackageInfo

NATIVE_EXTENSIONS: tuple[str, ...] = (".dll", ".pyd", ".so", ".dylib")


class MiraLoader(importlib.abc.Loader):
    """Loader for modules stored inside a .mira archive."""

    def __init__(
        self,
        package: MiraPackageInfo,
        path_in_zip: str,
        file_type: str,
        is_package: bool,
    ) -> None:
        """Create a loader.

        Args:
            package: Loaded package information.
            path_in_zip: Module path inside the archive.
            file_type: "pyc" or "native".
            is_package: Whether the module is a package.
        """
        self.package = package
        self.path_in_zip = path_in_zip
        self.file_type = file_type
        self.is_package = is_package

    def create_module(self, spec):  # type: ignore[override]
        """Use default module creation semantics."""
        return None

    def exec_module(self, module) -> None:  # type: ignore[override]
        """Execute the module from the .mira archive."""
        if self.file_type == "pyc":
            self._exec_pyc(module)
            return

        if self.file_type == "native":
            self._exec_native(module)
            return

        raise ImportError(f"Unsupported module type: {self.file_type}")

    def _exec_pyc(self, module) -> None:
        """Execute a compiled .pyc module from the archive."""
        data = self.package.zip_file.read(self.path_in_zip)
        if data[:4] != importlib.util.MAGIC_NUMBER:
            raise ImportError(f"Invalid bytecode magic for {self.path_in_zip}")

        code = marshal.loads(data[16:])
        module.__file__ = f"mira://{self.package.name}/{self.path_in_zip}"
        if self.is_package:
            module.__path__ = [module.__file__]
        exec(code, module.__dict__)

    def _exec_native(self, module) -> None:
        """Execute a native extension module extracted to a temp directory."""
        if not self.package.temp_dir:
            raise ImportError("Native module extraction directory not available")

        relative = self.path_in_zip.replace("dlls/", "", 1)
        file_path = os.path.join(self.package.temp_dir, relative)
        loader = importlib.machinery.ExtensionFileLoader(module.__name__, file_path)
        loader.exec_module(module)
