from typing import Any, Dict, List, Optional


Node = Dict[str, Any]


def _make_node(name: str, phone: str) -> Node:
    return {"name": name, "phone": phone, "left": None, "right": None}


def bst_insert(root: Optional[Node], name: str, phone: str) -> Node:
    new_node = _make_node(name, phone)

    if root is None:
        return new_node

    current = root
    parent = None

    while current is not None:
        parent = current
        if name < current["name"]:
            current = current["left"]
        elif name > current["name"]:
            current = current["right"]
        else:
            current["phone"] = phone
            return root

    if name < parent["name"]:
        parent["left"] = new_node
    else:
        parent["right"] = new_node

    return root


def bst_find(root: Optional[Node], name: str) -> Optional[str]:
    current = root
    while current is not None:
        if name < current["name"]:
            current = current["left"]
        elif name > current["name"]:
            current = current["right"]
        else:
            return current["phone"]
    return None


def _find_min_node(node: Node) -> Node:
    current = node
    while current["left"] is not None:
        current = current["left"]
    return current


def bst_delete(root: Optional[Node], name: str) -> Optional[Node]:
    if root is None:
        return None

    parent = None
    current = root

    while current is not None and current["name"] != name:
        parent = current
        if name < current["name"]:
            current = current["left"]
        else:
            current = current["right"]

    if current is None:
        return root

    if current["left"] is None or current["right"] is None:
        child = current["left"] if current["left"] is not None else current["right"]

        if parent is None:
            return child

        if parent["left"] is current:
            parent["left"] = child
        else:
            parent["right"] = child
        return root

    succ_parent = current
    successor = current["right"]
    while successor["left"] is not None:
        succ_parent = successor
        successor = successor["left"]

    current["name"] = successor["name"]
    current["phone"] = successor["phone"]

    successor_child = successor["right"]
    if succ_parent["left"] is successor:
        succ_parent["left"] = successor_child
    else:
        succ_parent["right"] = successor_child

    return root


def bst_list_all(root: Optional[Node]) -> List[Dict[str, str]]:
    result: List[Dict[str, str]] = []
    stack: List[Node] = []
    current = root

    while current is not None or stack:
        while current is not None:
            stack.append(current)
            current = current["left"]

        current = stack.pop()
        result.append({"name": current["name"], "phone": current["phone"]})
        current = current["right"]

    return result
