import hashlib
import uuid

DEFAULT_SALT = "snekker-de-snek-"
DEFAULT_NS = "snekker-de-snek-"


class UIDNS:
    def __init__(self, name: str) -> None:
        """Initialize UIDNS with a name."""
        self.name = name

    @property
    def bytes(self) -> bytes:
        """Return the bytes representation of the name."""
        return self.name.encode()


def uid(value: str = None, ns: str = DEFAULT_NS) -> str:
    """Generate a UUID based on the provided value and namespace.

    Args:
        value (str): The value to generate the UUID from. If None, a new UUID is created.
        ns (str): The namespace to use for UUID generation.

    Returns:
        str: The generated UUID as a string.
    """
    try:
        ns = ns.decode()
    except AttributeError:
        pass
    if not value:
        value = str(uuid.uuid4())
    try:
        value = value.decode()
    except AttributeError:
        pass

    return str(uuid.uuid5(UIDNS(ns), value))


def hash_sync(data: str, salt: str = DEFAULT_SALT) -> str:
    """Hash the given data with the specified salt using SHA-256.

    Args:
        data (str): The data to hash.
        salt (str): The salt to use for hashing.

    Returns:
        str: The hexadecimal representation of the hashed data.
    """
    try:
        data = data.encode(errors="ignore")
    except AttributeError:
        pass
    try:
        salt = salt.encode(errors="ignore")
    except AttributeError:
        pass
    salted = salt + data

    obj = hashlib.sha256(salted)
    return obj.hexdigest()


async def hash(data: str, salt: str = DEFAULT_SALT) -> str:
    return hash_sync(data, salt)


def verify_sync(string: str, hashed: str) -> bool:
    """Verify if the given string matches the hashed value.

    Args:
        string (str): The string to verify.
        hashed (str): The hashed value to compare against.

    Returns:
        bool: True if the string matches the hashed value, False otherwise.
    """
    return hash_sync(string) == hashed


async def verify(string: str, hashed: str) -> bool:
    return verify_sync(string, hashed)
