import logging

from pydantic import ValidationError

from labels.advisories import roots as roots_advisories
from labels.advisories.images import update_image_advisories
from labels.model.advisories import Advisory
from labels.model.package import Ecosystem, Package
from labels.utils.strings import format_exception

LOGGER = logging.getLogger(__name__)


ROOT_TYPES: set[Ecosystem] = {
    Ecosystem.NPM,
    Ecosystem.PUB,
    Ecosystem.NUGET,
    Ecosystem.MAVEN,
    Ecosystem.PACKAGIST,
    Ecosystem.PYPI,
    Ecosystem.RUBYGEMS,
    Ecosystem.GO,
    Ecosystem.SWIFTURL,
}

IMAGES_TYPES: set[Ecosystem] = {
    Ecosystem.ALPM,
    Ecosystem.DEBIAN,
    Ecosystem.ALPINE,
    Ecosystem.RPM,
}


def update_root_advisories(package: Package) -> list[Advisory]:
    safe_versions = roots_advisories.get_safe_versions(package.ecosystem, package.name)
    package.safe_versions = safe_versions
    return roots_advisories.get_vulnerabilities(
        package.ecosystem,
        package.name,
        package.version,
        safe_versions,
    )


def get_package_advisories(package: Package) -> list[Advisory] | None:
    try:
        pkg_advisories = []
        if package.ecosystem in ROOT_TYPES:
            pkg_advisories = update_root_advisories(package)
        if package.ecosystem in IMAGES_TYPES:
            pkg_advisories = update_image_advisories(package)
    except ValidationError as ex:
        LOGGER.exception(
            "Unable to complete package advisories",
            extra={
                "extra": {
                    "exception": format_exception(str(ex)),
                    "location": package.locations,
                    "ecosystem": package.ecosystem,
                },
            },
        )
        return None
    return pkg_advisories


def complete_package_advisories(package: Package) -> Package:
    if pkg_advisories := get_package_advisories(package):
        package.advisories = pkg_advisories
    return package
