import re
import uuid
from pathlib import Path
from urllib.parse import quote, urlunparse

from labels.model.advisories import Advisory
from labels.model.core import SbomConfig, SourceType
from labels.model.package import Ecosystem, Language, Package
from labels.model.relationship import Relationship, RelationshipType
from labels.model.resolver import Resolver
from labels.model.syft_sbom import SyftSBOM
from labels.resolvers.directory import Directory


def sanitize_name(text: str) -> str:
    return re.sub(r"[^a-zA-Z0-9.-]", "-", text)


def get_document_namespace(working_dir: str) -> str:
    input_type = "unknown-source-type"
    path_working_dir = Path(working_dir)

    if path_working_dir.is_file():
        input_type = "file"
    elif path_working_dir.is_dir():
        input_type = "dir"

    unique_id = uuid.uuid4()
    identifier = Path(input_type, str(unique_id))
    if working_dir != ".":
        identifier = Path(input_type, f"{working_dir}-{unique_id}")

    return urlunparse(
        ("https", "fluidattacks.com", str(identifier), "", "", ""),
    )


def get_relative_path(absolute_path: str) -> str:
    root_path = Path(absolute_path)
    current_dir = Path.cwd()
    try:
        return str(root_path.relative_to(current_dir))
    except ValueError:
        return absolute_path


def set_namespace_version(
    config: SbomConfig, resolver: Resolver | SyftSBOM
) -> tuple[str, str | None]:
    if config.source_type == SourceType.DIRECTORY and isinstance(resolver, Directory):
        return get_relative_path(resolver.root), None

    if (
        config.source_type
        in {
            SourceType.DOCKER,
            SourceType.ECR,
            SourceType.DOCKER_DAEMON,
            SourceType.ECR_WITH_CREDENTIALS,
        }
        and isinstance(resolver, SyftSBOM)
        and resolver.source
    ):
        return resolver.source.namespace, resolver.source.version

    return "", None


def create_packages_for_test() -> tuple[list[Package], list[Relationship]]:
    test_from_pkg = Package(
        name="source-package",
        version="1.0.0",
        locations=[],
        language=Language.PYTHON,
        ecosystem=Ecosystem.PYPI,
        p_url="pkg:test/source@1.0.0",
        ecosystem_data=None,
        found_by="python-pyproject-toml-cataloger",
        advisories=[
            Advisory(
                id="test-advisory",
                source="https://test-url.com",
                severity_level="HIGH",
                epss=0.75,
                percentile=8.5,
                details="Test advisory description",
                vulnerable_version=">=1.0.0",
                cpes=[],
                ecosystem="github",
                severity_v4=None,
            ),
        ],
    )
    test_to_pkg = Package(
        name="target-package",
        version="1.0.0",
        locations=[],
        language=Language.PYTHON,
        ecosystem=Ecosystem.PYPI,
        p_url="pkg:test/target@1.0.0",
        ecosystem_data=None,
        found_by="python-pyproject-toml-cataloger",
    )
    test_packages = [
        Package(
            name="test-package",
            version="1.0.0",
            locations=[],
            language=Language.PYTHON,
            ecosystem=Ecosystem.PYPI,
            p_url="pkg:python/test-package@1.0.0",
            ecosystem_data=None,
            found_by="python-pyproject-toml-cataloger",
        ),
        test_from_pkg,
        test_to_pkg,
    ]
    test_relationships = [
        Relationship(
            from_=test_from_pkg.id_,
            to_=test_to_pkg.id_,
            type=RelationshipType.DEPENDENCY_OF_RELATIONSHIP,
        ),
    ]
    return test_packages, test_relationships


def sanitize_spdx_path(text: str) -> str:
    return quote(text, safe="/-._~:")
