from __future__ import annotations

import importlib.util
from collections.abc import Sequence

from codebase_rag.constants import (
    EMBEDDING_PROVIDER_FASTEMBED,
    EMBEDDING_PROVIDER_UNIXCODER,
    MODULE_FASTEMBED,
    MODULE_QDRANT_CLIENT,
    MODULE_TORCH,
    MODULE_TRANSFORMERS,
)

_dependency_cache: dict[str, bool] = {}


def _check_dependency(module_name: str) -> bool:
    if module_name not in _dependency_cache:
        _dependency_cache[module_name] = (
            importlib.util.find_spec(module_name) is not None
        )
    return _dependency_cache[module_name]


def has_torch() -> bool:
    return _check_dependency(MODULE_TORCH)


def has_transformers() -> bool:
    return _check_dependency(MODULE_TRANSFORMERS)


def has_fastembed() -> bool:
    return _check_dependency(MODULE_FASTEMBED)


def has_qdrant_client() -> bool:
    return _check_dependency(MODULE_QDRANT_CLIENT)


def has_unixcoder_dependencies() -> bool:
    return has_torch() and has_transformers()


def has_semantic_dependencies() -> bool:
    from codebase_rag.config import settings

    provider = settings.EMBEDDING_PROVIDER.lower().strip()
    if provider == EMBEDDING_PROVIDER_FASTEMBED:
        return has_qdrant_client() and has_fastembed()
    if provider == EMBEDDING_PROVIDER_UNIXCODER:
        return has_qdrant_client() and has_unixcoder_dependencies()
    return False


def check_dependencies(required_modules: Sequence[str]) -> bool:
    return all(_check_dependency(module) for module in required_modules)


def get_missing_dependencies(required_modules: Sequence[str]) -> list[str]:
    return [module for module in required_modules if not _check_dependency(module)]
