"""Installation of .mira packages into a repository."""

from __future__ import annotations

import os
from typing import Any

from mira.library.repository import MiraRepository
from mira.library.resolver import PackageResolver


class MiraInstaller:
    """Install .mira packages with compatibility checks."""

    def __init__(
        self,
        repository: MiraRepository | None = None,
        resolver: PackageResolver | None = None,
    ) -> None:
        """Create an installer.

        Args:
            repository: Optional repository instance.
            resolver: Optional resolver instance.
        """
        self.repository = repository or MiraRepository()
        self.resolver = resolver or PackageResolver()

    def install(
        self,
        mira_path: str,
        target_dir: str | None = None,
        key: str | None = None,
    ) -> str:
        """Install a .mira package.

        Args:
            mira_path: Path to the .mira file.
            target_dir: Optional custom repository directory.
            key: Optional encryption key for protected archives.

        Returns:
            Destination path in the repository.
        """
        repository = self.repository
        if target_dir is not None:
            repository = MiraRepository(base_dir=target_dir)

        manifest = self.resolver.read_manifest(mira_path, key=key)
        compatible, warnings = self.resolver.check_compatibility(manifest)
        if not compatible:
            details = "; ".join(warnings) if warnings else "incompatible package"
            raise RuntimeError(f"Package not compatible: {details}")

        dest = repository.install(mira_path)
        name = manifest.get("name", "unknown")
        version = manifest.get("version", "unknown")
        print(f"Installed {name} {version} -> {dest}")
        return dest

    def install_from_dir(self, directory: str, key: str | None = None) -> list[str]:
        """Install all .mira packages from a directory.

        Args:
            directory: Directory containing .mira files.
            key: Optional encryption key for protected archives.
        """
        if not os.path.isdir(directory):
            raise RuntimeError(f"Directory not found: {directory}")

        installed: list[str] = []
        for filename in os.listdir(directory):
            if not filename.endswith(".mira"):
                continue
            path = os.path.join(directory, filename)
            installed.append(self.install(path, key=key))
        return installed
