from pathlib import Path
from typing import Optional, List, Dict

from phidata.workspace.config import WorkspaceConfig
from phiterm.workspace.ws_utils import get_ws_config_dir_path

from phiterm.utils.log import logger


def add_ws_dir_to_path(ws_root_path: Path) -> None:
    # Add ws_root_path to sys.path so is treated as a package
    try:
        import sys

        logger.debug(f"Adding {ws_root_path} to path")
        sys.path.insert(0, str(ws_root_path))
    except Exception as e:
        logger.warning(
            f"Could not add {ws_root_path} to Path. This will break workspace imports"
        )
        logger.exception(e)


def get_python_objects_from_module(module_path: Path) -> Dict:
    """
    Returns a list of python objects from a module
    """
    import importlib.util
    from importlib.machinery import ModuleSpec

    # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
    # Create a ModuleSpec
    module_spec: Optional[ModuleSpec] = importlib.util.spec_from_file_location(
        "module", module_path
    )
    # Using the ModuleSpec create a module
    if module_spec:
        module = importlib.util.module_from_spec(module_spec)
        module_spec.loader.exec_module(module)  # type: ignore
        return module.__dict__
    else:
        return {}


def load_workspace(ws_root_path: Path) -> WorkspaceConfig:
    """
    Loads a workspace into a WorkspaceConfig
    """

    ws_config: WorkspaceConfig = WorkspaceConfig()
    config_dir_path: Optional[Path] = get_ws_config_dir_path(ws_root_path)
    if config_dir_path is not None:
        logger.debug(f"--^^-- Loading workspace from: {config_dir_path}")
        workspace_config_objects = {}
        config_files = config_dir_path.rglob("*.py")
        for _config_file in config_files:
            if _config_file.name == "__init__.py":
                continue
            logger.debug(f"Reading file: {_config_file}")
            try:
                python_objects = get_python_objects_from_module(_config_file)
                for obj_name, obj in python_objects.items():
                    _type_name = obj.__class__.__name__
                    if _type_name in [
                        "WorkspaceSettings",
                        "DockerConfig",
                        "K8sConfig",
                        "AwsConfig",
                    ]:
                        workspace_config_objects[obj_name] = obj
            except Exception as e:
                pass

        logger.debug(f"workspace_config_objects: {workspace_config_objects}")
        for obj_name, obj in workspace_config_objects.items():
            _obj_type = obj.__class__.__name__
            logger.debug(f"Adding {obj_name}: | Type: {_obj_type}")
            if _obj_type == "WorkspaceSettings":
                ws_config.ws_settings = obj
                try:
                    ws_config.default_env = obj.dev_env
                except Exception as e:
                    pass
                try:
                    ws_config.aws_region = obj.aws_region
                except Exception as e:
                    pass
            elif _obj_type == "DockerConfig":
                if ws_config.docker is None:
                    ws_config.docker = []
                ws_config.docker.append(obj)
                ws_config.default_config = "docker"
            elif _obj_type == "K8sConfig":
                if ws_config.k8s is None:
                    ws_config.k8s = []
                ws_config.k8s.append(obj)
            elif _obj_type == "AwsConfig":
                if ws_config.aws is None:
                    ws_config.aws = []
                ws_config.aws.append(obj)

    return ws_config
