

from typing import Any, Dict, List, Optional

from linked_list import ll_insert, ll_find, ll_delete, ll_list_all


Bucket = Optional[Dict[str, Any]]


def _hash_name(name: str, buckets_count: int) -> int:
    if buckets_count <= 0:
        return 0
    return sum(ord(ch) for ch in name) % buckets_count


def ht_insert(buckets: List[Bucket], name: str, phone: str) -> List[Bucket]:
    if not buckets:
        return buckets
    index = _hash_name(name, len(buckets))
    buckets[index] = ll_insert(buckets[index], name, phone)
    return buckets


def ht_find(buckets: List[Bucket], name: str) -> Optional[str]:
    if not buckets:
        return None
    index = _hash_name(name, len(buckets))
    return ll_find(buckets[index], name)


def ht_delete(buckets: List[Bucket], name: str) -> List[Bucket]:
    if not buckets:
        return buckets
    index = _hash_name(name, len(buckets))
    buckets[index] = ll_delete(buckets[index], name)
    return buckets


def ht_list_all(buckets: List[Bucket]) -> List[Dict[str, str]]:
    records: List[Dict[str, str]] = []
    for head in buckets:
        records.extend(ll_list_all(head))
    return sorted(records, key=lambda x: x["name"])
