"""
bundles.py

Expanded bundle importer module — now with MANY more bundles and *_vanilla
variants (no third-party deps). Drop this file into your project and use like:

    from bundles import networking, encryption, encryption_vanilla
    print(networking)
    print(encryption.encryption_fernet)

Design notes:
 - Every bundle X has an optional X_vanilla variant that contains only
   Python standard-library modules (i.e., no third-party packages required).
 - Third-party modules are included where useful but are optional; if not
   installed they will be present as None on the bundle object.
 - The module intentionally avoids providing exploitative or malicious
   functionality. It only aggregates imports. Use responsibly and legally.

"""

from __future__ import annotations

import importlib
import types
import sys
from types import ModuleType
from typing import Dict, List, Any

# --------------------------- Configuration ---------------------------
# Add or remove items here. Use dotted names for submodules when appropriate.
BUNDLES: Dict[str, List[str]] = {
    # ---------------- Math ----------------
    "mathematics": [
        "math",
        "cmath",
        "fractions",
        "decimal",
        "statistics",
        "random",
        "numbers",
        "itertools",
        "functools",
        "numpy",
        "scipy",
        "sympy",
    ],
    "mathematics_vanilla": [
        "math",
        "cmath",
        "fractions",
        "decimal",
        "statistics",
        "random",
        "numbers",
        "itertools",
        "functools",
    ],

    # ---------------- Programming helpers ----------------
    "programming": [
        "sys",
        "typing",
        "inspect",
        "importlib",
        "pkgutil",
        "traceback",
        "logging",
        "argparse",
        "configparser",
        "contextlib",
        "pathlib",
        "dataclasses",
        "threading",
        "concurrent.futures",
    ],
    "programming_vanilla": [
        "sys",
        "typing",
        "inspect",
        "importlib",
        "traceback",
        "logging",
        "argparse",
        "contextlib",
        "pathlib",
        "dataclasses",
        "threading",
    ],

    # ---------------- Networking ----------------
    "networking": [
        "socket",
        "selectors",
        "ipaddress",
        "asyncio",
        "http",
        "urllib",
        "requests",
        "http.client",
        "ftplib",
        "smtplib",
        "ssl",
        "netifaces",
        "psutil",
    ],
    "networking_vanilla": [
        "socket",
        "selectors",
        "ipaddress",
        "asyncio",
        "http",
        "urllib",
        "http.client",
        "ftplib",
        "smtplib",
        "ssl",
    ],

    # ---------------- System administration ----------------
    "admin": [
        "os",
        "subprocess",
        "shutil",
        "platform",
        "pwd",
        "grp",
        "getpass",
        "psutil",
        "pathlib",
        "winreg",
        "win32api",
    ],
    "admin_vanilla": [
        "os",
        "subprocess",
        "shutil",
        "platform",
        "getpass",
        "pathlib",
    ],

    # ---------------- Remote admin (legit libs only) ----------------
    "remote_admin": [
        "paramiko",
        "fabric",
        "winrm",
        "pywinrm",
    ],
    "remote_admin_vanilla": [
        "subprocess",
        "socket",
    ],

    # ---------------- Data ----------------
    "data": [
        "json",
        "csv",
        "sqlite3",
        "pickle",
        "bz2",
        "gzip",
        "pandas",
        "sqlalchemy",
    ],
    "data_vanilla": [
        "json",
        "csv",
        "sqlite3",
        "pickle",
        "bz2",
        "gzip",
    ],

    # ---------------- Databases ----------------
    "databases": [
        "sqlite3",
        "psycopg2",
        "pymysql",
        "mysql",
        "redis",
        "pymongo",
    ],
    "databases_vanilla": [
        "sqlite3",
    ],

    # ---------------- Web development ----------------
    "web": [
        "wsgiref",
        "http.server",
        "flask",
        "django",
        "fastapi",
        "starlette",
    ],
    "web_vanilla": [
        "wsgiref",
        "http.server",
    ],

    # ---------------- Testing & debugging ----------------
    "testing": [
        "unittest",
        "pytest",
        "pdb",
        "trace",
        "faulthandler",
    ],
    "testing_vanilla": [
        "unittest",
        "pdb",
        "trace",
    ],

    # ---------------- Tutorial / Recording ----------------
    # tutorial has many third-party helpers; tutorial_vanilla uses stdlib only
    "tutorial": [
        "cv2",
        "PIL",
        "pyautogui",
        "sounddevice",
        "pyaudio",
        "ffmpeg",
        "moviepy",
        "mss",
    ],
    "tutorial_vanilla": [
        "tkinter",
        "wave",
        "audioop",
        "os",
        "subprocess",
    ],

    # ---------------- Security / Encryption ----------------
    "encryption": [
        "hashlib",
        "hmac",
        "ssl",
        "secrets",
        "base64",
        "binascii",
        "cryptography",
        "cryptography.fernet",
        "Crypto",
        "pycryptodome",
    ],
    "encryption_vanilla": [
        "hashlib",
        "hmac",
        "ssl",
        "secrets",
        "base64",
        "binascii",
    ],

    # encoding helpers
    "encoding": ["base64", "codecs", "binascii", "quopri"],
    "encoding_vanilla": ["base64", "codecs", "binascii"],

    # ---------------- Machine learning ----------------
    "ml": [
        "numpy",
        "scipy",
        "sklearn",
        "tensorflow",
        "torch",
        "keras",
        "transformers",
    ],
    "ml_vanilla": [
        "math",
        "random",
    ],

    # ---------------- Visualization ----------------
    "visualization": [
        "matplotlib",
        "seaborn",
        "plotly",
        "bokeh",
        "altair",
    ],
    "visualization_vanilla": [
        "tkinter",
    ],

    # ---------------- DevOps / Cloud ----------------
    "devops": ["subprocess", "yaml", "json", "boto3", "docker", "fabric"],
    "devops_vanilla": ["subprocess", "json"],

    # ---------------- Packaging ----------------
    "packaging": ["setuptools", "packaging", "pip"],
    "packaging_vanilla": ["distutils", "pip"],

    # ---------------- Utilities ----------------
    "utils": [
        "time",
        "datetime",
        "uuid",
        "collections",
        "itertools",
        "functools",
        "re",
        "hashlib",
    ],
    "utils_vanilla": [
        "time",
        "datetime",
        "uuid",
        "collections",
        "itertools",
        "functools",
        "re",
    ],

    # ---------------- Hardware / GPIO ----------------
    "hardware": ["serial", "RPi", "smbus"],
    "hardware_vanilla": ["os"],

    # ---------------- Game development ----------------
    "game_dev": [
        "pygame",
        "pyglet",
        "moderngl",
        "panda3d",
        "ursina",
        "pyopengl",
        "cocos2d",
    ],
    "game_dev_vanilla": [
        "tkinter",
        "turtle",
        "random",
        "time",
    ],

    # ---------------- Low-level / Reverse engineering helpers ----------------
    "low_leveling": [
        "ctypes",
        "cffi",
        "struct",
        "mmap",
        "array",
        "socket",
        "pyelftools",
        "capstone",
        "unicorn",
        "keystone",
        "lief",
    ],
    "low_leveling_vanilla": [
        "ctypes",
        "struct",
        "mmap",
        "array",
        "sys",
    ],
}

# --------------------------- Implementation ---------------------------

_BUNDLE_CACHE: Dict[str, types.SimpleNamespace] = {}


class BundleNamespace(types.SimpleNamespace):
    def __init__(self, name: str, modules: Dict[str, Any]):
        super().__init__(**modules)
        self.__bundle_name__ = name

    def __repr__(self) -> str:
        lines = [f"<Bundle '{self.__bundle_name__}':"]
        for key in sorted(self.__dict__):
            if key.startswith("_"):
                continue
            mod = getattr(self, key)
            status = "loaded" if isinstance(mod, ModuleType) else (
                "missing" if mod is None else repr(type(mod))
            )
            lines.append(f" - {key} ({status})")
        lines.append(">")
        return "\n".join(lines)

    def __dir__(self):
        default = list(super().__dir__())
        attrs = [k for k in self.__dict__.keys() if not k.startswith("_")]
        return sorted(set(default + attrs))


def _import_module_safely(name: str):
    try:
        module = importlib.import_module(name)
        return module
    except Exception:
        return None


def _build_bundle(name: str) -> BundleNamespace:
    if name in _BUNDLE_CACHE:
        return _BUNDLE_CACHE[name]
    if name not in BUNDLES:
        raise AttributeError(f"No such bundle: {name}")
    modules = {}
    for mod_name in BUNDLES[name]:
        attr_name = mod_name.replace(".", "_")
        module = _import_module_safely(mod_name)
        modules[attr_name] = module
    bundle = BundleNamespace(name, modules)
    _BUNDLE_CACHE[name] = bundle
    return bundle


def __getattr__(name: str):
    if name in BUNDLES:
        return _build_bundle(name)
    raise AttributeError(f"module 'bundles' has no attribute '{name}'")


def list_bundles() -> List[str]:
    return sorted(BUNDLES.keys())


def show_bundle(name: str) -> str:
    bundle = _build_bundle(name)
    return repr(bundle)


__all__ = list(list_bundles()) + ["list_bundles", "show_bundle"]

__doc__ += "\n\nAvailable bundles (names): " + ", ".join(sorted(BUNDLES.keys()))

# EOF