"""
    This module contains all error that may occur during the management of
    virtual environments handled by uv.
"""

import re

from wox.subprocess_error_detection.utils import (
    detect_error_from_stderr,
    detect_sentence_with_fill_in_blank
)
from wox.utils import get_python_version_from_command
from wox.wox_exceptions import (
    DependencyConflictError,
    DiskFullError,
    PackageNotFoundError,
    PermissionDeniedError,
    PipTimeoutError,
    PythonInterpreterUnstableError
)


def detect_uv_errors(stderr_output, command, python_interpreter):
    """
        Detects uv-related errors upon dependencies installation.

        Parameters
        ----------
        stderr_output : str
            Output captured from the subprocess stderr stream.
        command : str
            Command executed by subprocess.
        python_interpreter : PythonInterpreter
            Python interpreter with its version and path.

        Raises
        ------
        DependencyConflictError
            Dependency conflict occurs during package installation.
        DiskFullError
            Disk is full and command cannot write data.
        PipTimeoutError
            Pip cannot reach package server.
        PackageNotFoundError
            Package is missing or wrongly spelled.
        PermissionDeniedError
            Permissions prevent writing data.
        PythonInterpreterUnstableError
            The Python interpreter crashes at the C-level.
    """

    check_dependency_conflict_error(stderr_output, command)
    check_disk_full_error(stderr_output, command)
    check_pip_timeout_error(stderr_output, command)
    check_package_not_found_error(stderr_output, command, python_interpreter.path)
    check_permission_denied_error(stderr_output, command)
    check_python_interpreter_unstable_error(stderr_output,
        command,
        python_interpreter.version
    )

def check_dependency_conflict_error(stderr_output, command):

    if (
        'install' in command and \
        detect_sentence_with_fill_in_blank(stderr_output,
            'your requirements and * are incompatible'
        )
    ):
        raise DependencyConflictError

def check_disk_full_error(stderr_output, command):
    if 'install' in command and detect_error_from_stderr(stderr_output, ['error 28']):
        raise DiskFullError

def check_pip_timeout_error(stderr_output, command):
    if 'install' in command and detect_error_from_stderr(stderr_output,
        ['connection refused (os error 111)', 'error sending request for url']
    ):
        raise PipTimeoutError

def check_package_not_found_error(stderr_output, command, python_interpreter_path):
    if ('install' in command and \
        detect_error_from_stderr(stderr_output, ['there are no versions'])
    ):
        environment = python_interpreter_path.parent.parent.name
        match = re.search(r'there are no versions of (\S+)', stderr_output)
        if match:
            missing_package = match.group(1)
        raise PackageNotFoundError(missing_package, environment)

def check_permission_denied_error(stderr_output, command):
    if (
        'install' in command and \
        detect_error_from_stderr(stderr_output,['os error 13'])
    ):
        raise PermissionDeniedError

def check_python_interpreter_unstable_error(stderr_output, command, version):
    if (
        (
            ('venv' in command or 'install' in command) and \
            detect_error_from_stderr(stderr_output,
                [
                    'died with', 'sigsegv',
                    'segmentation fault', 'core dumped',
                    'problem confirming the ssl certificate',
                    'ssl module is not available',
                    'ssl module in python is not available'
                ]
            )
        ) or (
            'cannot open shared object file' in stderr_output.lower() and \
            'libpython' in stderr_output.lower()
        )
    ):
        if not version:
            version = get_python_version_from_command(command)
        raise PythonInterpreterUnstableError(version)
