from structures.LinkedList import ll_insert, ll_find, ll_delete


def _hash_key(key: str, capacity: int) -> int:
    acc = 0
    for ch in key:
        acc = (acc * 31 + ord(ch)) % capacity
    return acc


def ht_insert(storage: list | None, key: str, value: str, capacity: int = 50) -> list:
    if storage is None:
        storage = [None] * capacity

    idx = _hash_key(key, len(storage))
    storage[idx] = ll_insert(storage[idx], key, value)
    return storage


def ht_find(storage: list | None, key: str) -> str | None:
    if storage is None:
        return None

    idx = _hash_key(key, len(storage))
    return ll_find(storage[idx], key)


def ht_delete(storage: list | None, key: str) -> list | None:
    if storage is None:
        return None

    idx = _hash_key(key, len(storage))
    storage[idx] = ll_delete(storage[idx], key)
    return storage


def ht_list_all(storage: list | None) -> list:
    if storage is None:
        return []

    result = []
    for chain in storage:
        node = chain
        while node is not None:
            result.append((node['name'], node['phone']))
            node = node['next']

    result.sort(key=lambda x: x[0])
    return result