from packaging.specifiers import SpecifierSet

import wox.subprocessor as subprocessor

from wox.constants import DOT_WOX, MSV_VIRTUALENV
from wox.logger.logger_setup import wox_logger
from wox.wox_exceptions import MissingWoxKeywordError
from wox.utils import rmtree_with_retry


def venv_deletion(tasks):
    """
        Deletes virtual environments used during the wox session which
        were created in a previous wox session.

        Parameters
        ----------
        tasks : dict
            Tasks declared in the .toml file.

        Raises
        ------
        MissingWoxKeywordError
            Required wox keyword missing in .toml file.
    """

    for task in tasks:

        try:
            envlist = tasks[task]['envlist']
        except KeyError as e:
            raise MissingWoxKeywordError(e)

        for env in envlist:

            env_path = DOT_WOX / env
            if env_path.exists():
                wox_logger.info(f'Deletion of venv {env}.')
                try:
                    rmtree_with_retry(env_path)
                except Exception as e:
                    wox_logger.warning(f'{type(e).__name__}: {e}')
                    continue
                else:
                    wox_logger.debug(f'Venv {env} deleted!')
            else:
                wox_logger.warning(
                    f"Unable to delete '{env}': virtual environment "
                    f"not found on '{env_path}'"
                )

def create_venv(env_path, python_interpreter, with_uv = False):
    """
        Creates virtual environment running during the wox session.

        Parameters
        ----------
        env_path : pathlib.Path
            Path to the virtual environment.
        python_interpreter : PythonInterpreter
            Discovered Python interpreter with its version and path.
        with_uv : bool
            If True, switches pip to uv.

        Raises
        ------
        PythonInterpreterUnstableError
            The Python interpreter crashes at the C-level.
    """

    wox_logger.debug(f'Creation of venv {env_path.name} on path {env_path}.')

    if with_uv and python_interpreter.version in SpecifierSet(MSV_VIRTUALENV):
        subprocessor.run_command(
            f'uv venv --python {python_interpreter.path} {str(env_path)}',
            python_interpreter = python_interpreter
        )
    else:
        subprocessor.run_command(
            f'{python_interpreter.path} -m venv {str(env_path)}',
            python_interpreter = python_interpreter
        )

    wox_logger.debug(f'Venv {env_path.name} created!')


