import json
import logging
import os
import shutil
from pathlib import Path


def stats_pathname(pathname: Path | str) -> bool:
    current_pathname = Path(pathname)
    return current_pathname.is_dir()


def create_folder_if_not_exists(
    pathname: Path | str, force_cleanup: bool = False
) -> None:
    """Create a folder given its path.

    Args:
        pathname: folder Path or string
        force_cleanup: if True, remove existing files or non-empty dirs at the path;
                       if False, raise FileExistsError (non-empty dir) or OSError (file at path)
    """
    current_pathname = Path(pathname)
    logging.info(
        f"Pathname exists? {current_pathname.exists()}, That's a folder? {current_pathname.is_dir()}..."
    )

    if current_pathname.exists():
        if current_pathname.is_file() or current_pathname.is_symlink():
            if force_cleanup:
                logging.info(
                    f"Removing file at {current_pathname} before folder creation."
                )
                current_pathname.unlink()
            else:
                raise OSError(f"file exists at folder path: {current_pathname}")
        elif current_pathname.is_dir() and any(current_pathname.iterdir()):
            contents = [p.name for p in current_pathname.iterdir()]
            if force_cleanup:
                logging.info(
                    f"Removing non-empty directory {current_pathname}, contents: {contents}"
                )
                shutil.rmtree(current_pathname)
            else:
                raise FileExistsError(
                    f"non-empty directory: {current_pathname}, contents: {contents}"
                )

    logging.info(f"Creating pathname: {current_pathname} ...")
    current_pathname.mkdir(mode=0o770, parents=True, exist_ok=True)

    logging.info(f"assertion: pathname exists and is a folder: {current_pathname} ...")
    if not current_pathname.is_dir():
        raise OSError(f"folder not found: {current_pathname}.")


def folders_creation(
    folders_map: dict | str | None = None,
    force_cleanup: bool = False,
) -> None:
    """Create all folders listed within the folders_map argument (dict or json string).

    If folders_map is None, loads from the 'FOLDERS_MAP' env variable.
    Existing non-empty directories are silently skipped (FileExistsError).
    Config errors (malformed JSON, missing env) always raise.

    Args:
        folders_map: dict or string map of folder string
        force_cleanup: if True, remove existing files or non-empty dirs at each path
    """
    enforce_validation_with_getenv = folders_map is None
    if enforce_validation_with_getenv:
        folders_map = os.getenv("FOLDERS_MAP")
    if folders_map is None:
        raise TypeError("folders_map is None and FOLDERS_MAP env var is not set")
    folders_dict = (
        folders_map if isinstance(folders_map, dict) else json.loads(folders_map)
    )
    for folder_env_ref, folder_env_path in folders_dict.items():
        logging.info(
            f"folder_env_ref:{folder_env_ref}, folder_env_path:{folder_env_path}."
        )
        try:
            create_folder_if_not_exists(folder_env_path, force_cleanup=force_cleanup)
        except FileExistsError:
            logging.debug(f"folder already exists, skipping: {folder_env_path}")
            continue
        if (
            enforce_validation_with_getenv
            and os.getenv(folder_env_ref) != folder_env_path
        ):
            raise IOError(f"wrong folder path: {folder_env_path} #")


if __name__ == "__main__":
    folders_creation()
