"""
Entry point configuration for Investigation experiments.

This file should be created in your project's 'entry/' directory to define:
1. LIST_OF_ARGS: List of argument classes for your experiments
2. LIST_OF_CLUSTERS: List of cluster names (optional, for Slurm integration)
3. parameter2SlurmJob: Function to convert parameters to Slurm jobs

Example structure:
    entry/
    └── __init__.py  # This file

See examples/ctrl/entry/__init__.py for a complete example.
"""

from pathlib import Path
from investigation import storage_path, entry_path, cwd, env, investigation_home

if cwd != investigation_home:

    def load_module_from_path(module_name: str, directory: Path):
        import importlib.util
        import sys
        """
        从指定的目录动态加载一个模块。

        :param module_name: 模块名 (例如 'entry')
        :param directory: 模块所在的目录
        :return: 加载的模块对象，如果失败则返回 None
        """
        init_file = directory / module_name / '__init__.py'

        sys.path.insert(0, str(directory))

        if not init_file.exists():
            print(f"错误: 找不到模块初始化文件: {init_file}")
            raise FileNotFoundError(f"找不到模块初始化文件: {init_file}")
        # 1. 创建模块规范 (module spec)
        spec = importlib.util.spec_from_file_location(module_name, init_file)
        if spec is None:
            raise ImportError(f"无法创建模块规范: {module_name}")

        # 2. 根据规范创建模块对象
        module = importlib.util.module_from_spec(spec)

        # 3. 将模块添加到sys.modules中，这样模块内部的相对导入也能正常工作
        sys.modules[module_name] = module

        # 4. 执行模块代码
        spec.loader.exec_module(module)
        sys.path.pop(0)

        return module

    try:

        entry = load_module_from_path("entry", cwd)
        LIST_OF_CLUSTERS = entry.LIST_OF_CLUSTERS
        LIST_OF_ARGS = entry.LIST_OF_ARGS
        parameter2SlurmJob = entry.parameter2SlurmJob
        hostname = entry.hostname
        CLUSTER_CONFIG = entry.CLUSTER_CONFIG

    except ImportError as e:
        raise ImportError("无法加载 entry 模块。请确保在项目的 'entry/' 目录下创建 '__init__.py' 文件，"
                          "并定义 LIST_OF_ARGS, LIST_OF_CLUSTERS 和 parameter2SlurmJob 函数。"
                          "参考 examples/ctrl/entry/__init__.py 获取完整示例。") from e
else:
    from investigation.doeargs.args import ExampleArgs
    from typing import Type, List, Dict
    from slurming.SlurmJob.job import SlurmJob
    import os

    hostname = os.uname().nodename
    # Define your experiment argument classes here
    # These should inherit from ExampleArgs or be compatible dataclasses
    LIST_OF_ARGS: List[Type[ExampleArgs]] = []

    # Define your cluster names for Slurm job submission (optional)
    LIST_OF_CLUSTERS: List[str] = []

    CLUSTER_CONFIG = {
        "clusterB-cpu": {
            "hostname": "clusterB-nextgen",
            "mem_per_cpu": 4,
            "min_cores": 1,
            "partition": ["nextgen"],
            "core_per_job": 1,
            "max_num_cpus": 48,
            "max_num_gpus": 0,
        },
        "clusterB-gpu": {
            "hostname": "clusterB-nextgen",
            "mem_per_cpu": 10.7,
            "min_cores": 1,
            "partition": [
                "quad",
            ],
            "core_per_job": 1,
            "max_num_cpus": 48,
            "max_num_gpus": 2,
        },
        "clusterC-dense": {
            "hostname": "clusterC",
            "mem_per_cpu": 4.4,
            "min_cores": 1,
            "vip": ["clusterB", "clusterA"],
            "partition": ["cpu", "cpu-exp"],
        },
        "clusterA-cpu": {
            "hostname": "clusterA",
            "mem_per_cpu": 4.84,
            "min_cores": 1,
            "vip": ["clusterB"],
            "partition": ["cpu"],
            "max_num_cpus": 48,
            "max_num_gpus": 0,
        },
        "clusterA-gpu": {
            "hostname": "clusterA",
            "mem_per_cpu": 9.00,
            "min_cores": 1,
            "vip": ["clusterB"],
            "partition": ["gpu"],
            "max_num_cpus": 48,
            "max_num_gpus": 1,
        }
    }

    def parameter2SlurmJob(param_dict: Dict, ) -> SlurmJob:
        """
        Convert a parameter dictionary to a SlurmJob instance.

        This function should be implemented to define how your experiment
        parameters map to Slurm job configurations. It's called by the
        investigation to generate shell scripts for each experiment case.

        Args:
            param_dict (Dict): A dictionary containing parameters for the Slurm job.
                These come from your DoE configuration and argument classes.

        Returns:
            SlurmJob: An instance of SlurmJob configured with the provided parameters.

        Example:
            >>> def parameter2SlurmJob(param_dict: Dict) -> SlurmJob:
            >>>     return SlurmJob(
            >>>         account="YOUR_ACCOUNT",
            >>>         content=[
            >>>             make_command(
            >>>                 "python",
            >>>                 params1_dict={"m": "your.module"},
            >>>                 params2_dict=param_dict,
            >>>                 connection=" ",
            >>>             ),
            >>>         ],
            >>>         cpus_per_task=4,
            >>>         gpus=1,
            >>>     )
        """
        raise NotImplementedError("This function should be implemented in your project's entry/__init__.py file. "
                                  "See examples/ctrl/entry/__init__.py for a complete example.")
