import logging

from packageurl import (
    PackageURL,
)
from pydantic import (
    BaseModel,
    ConfigDict,
    ValidationError,
)

from labels.advisories import (
    roots as advisories,
)
from labels.file.location import (
    Location,
)
from labels.internal.collection.types import ParsedValue
from labels.model.core import (
    Language,
    Package,
    PackageType,
)
from labels.utils.strings import format_exception

LOGGER = logging.getLogger(__name__)


class SwiftPackageManagerResolvedEntry(BaseModel):
    revision: str
    model_config = ConfigDict(frozen=True)


class CocoaPodfileLockEntry(BaseModel):
    checksum: str
    model_config = ConfigDict(frozen=True)


def new_cocoa_pods_package(
    name: str,
    version: str,
    hash_: ParsedValue,
    location: Location,
) -> Package | None:
    if not isinstance(hash_, str):
        return None
    try:
        return Package(
            name=name,
            version=version,
            p_url=cocoapods_package_url(name, version),
            locations=[location],
            type=PackageType.CocoapodsPkg,
            language=Language.SWIFT,
            metadata=CocoaPodfileLockEntry(checksum=hash_),
            licenses=[],
        )
    except ValidationError as ex:
        LOGGER.warning(
            "Malformed package. Required fields are missing or data types are incorrect.",
            extra={
                "extra": {
                    "exception": format_exception(str(ex)),
                    "location": location.path(),
                },
            },
        )
        return None


def new_swift_package_manager_package(
    *,
    name: str,
    version: str,
    source_url: ParsedValue | None,
    revision: ParsedValue | None,
    location: Location,
) -> Package | None:
    try:
        return Package(
            name=name,
            version=version,
            p_url=swift_package_manager_package_url(name, version, source_url),
            locations=[location],
            type=PackageType.SwiftPkg,
            language=Language.SWIFT,
            metadata=SwiftPackageManagerResolvedEntry(revision=revision)
            if revision and isinstance(revision, str)
            else None,
            licenses=[],
        )
    except ValidationError as ex:
        LOGGER.warning(
            "Malformed package. Required fields are missing or data types are incorrect.",
            extra={
                "extra": {
                    "exception": format_exception(str(ex)),
                    "location": location.path(),
                },
            },
        )
        return None


def cocoapods_package_url(
    name: str,
    version: str,
) -> str:
    return PackageURL("cocoapods", "", name, version, None, "").to_string()  # type: ignore


def swift_package_manager_package_url(
    name: str,
    version: str,
    source_url: ParsedValue | None,
) -> str:
    return PackageURL(  # type: ignore
        "swift",
        source_url.replace("https://", "", 1) if source_url and isinstance(source_url, str) else "",
        name,
        version,
        None,
        "",
    ).to_string()


def _update_advisories(package: Package) -> None:
    pkg_advisories = advisories.get_vulnerabilities("swift", package.name, package.version)
    if pkg_advisories:
        package.advisories = pkg_advisories


def complete_package(package: Package) -> Package:
    _update_advisories(package)

    return package
