# Исходный код components.navbar_component

    """Модуль компонента панели навигации. Содержит класс для работы с элементами навигации."""

    from playwright.sync_api import Page, Locator
    from tools.logger import get_logger
    from locators.navigation_panel_locators import NavigationPanelLocators
    from components.base_component import BaseComponent

    logger = get_logger("NAVIGATION_PANEL")

    class NavigationPanelComponent(BaseComponent):
        """Компонент панели навигации. Предоставляет методы для взаимодействия с ней."""

        def __init__(self, page: Page):
            """Инициализирует компонент панели навигации.

            Args:
                page: Экземпляр страницы Playwright.
            """

            super().__init__(page)

        # Действия:

        def click_item(self, locator: str | Locator, item_name: str) -> None:
            """Кликает по элементу с указанным текстом.

            Args:
                locator: Локатор элемента или строка с CSS/XPath.
                item_name: Текст элемента для клика.
            """

            loc = self.get_locator(locator)
            loc.get_by_text(item_name).click()

        def click_sub_item(self, node_root_locator: str | Locator, item_name: str, parent: None|str) -> None:
            """Кликает по вложенному элементу с указанным текстом.

            Args:
                node_root_locator: Локатор для поиска корневых элементов дерева.
                item_name: Текст элемента для клика.
            """

            def find_and_click_item(page, root_locator, item_name: str, parent: None|str) -> Locator|None:
                # Находим все локаторы корневых узлов на текущем уровне
                nodes_count = root_locator.locator('>div.v-treeview-node').count()

                # Если искомый элемент находится на данном уровне, вычисляем локатор и делаем клик
                if parent is None:
                    for index in range(nodes_count):
                        node = root_locator.locator(f">div:nth-child({index + 1})").first
                        node_content = node.locator('div.v-treeview-node__content')
                        if node_content.count() > 0:
                            node_text = node_content.first.inner_text().strip()
                            if item_name == node_text:
                                node_attr = node.get_attribute('class')
                                if "v-treeview-node--leaf" not in node_attr:
                                    toggle_button = node.locator(
                                        NavigationPanelLocators.NODE_ROOT
                                    ).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
                                    toogle_class_attr = toggle_button.get_attribute('class')
                                    if "v-treeview-node__toggle--open" not in toogle_class_attr:
                                        toggle_button.click()
                                else:
                                    node.locator(NavigationPanelLocators.NODE_ROOT).click()
                                page.wait_for_timeout(1000)
                                return node

                # Если элемента нет, рекурсивно ищем дальше
                for index in range(nodes_count):
                    node = root_locator.locator(f">div:nth-child({index + 1})").first

                    # Извлекаем аттрибуты из корневого узла
                    node_class_attr = node.get_attribute('class')

                    is_expanded = False
                    has_children = False

                    # Проверяем лист это или начало поддерева
                    if "v-treeview-node--leaf" not in node_class_attr:
                        # Проверяем, является ли узел раскрытым
                        class_attr = node.locator(
                            NavigationPanelLocators.NODE_ROOT
                        ).locator(NavigationPanelLocators.TOGGLE_BUTTON).first.get_attribute('class')
                        if "v-treeview-node__toggle--open" in class_attr:
                            is_expanded = True

                        # Если узел закрыт можем его раскрыть
                        if is_expanded is False:
                            toggle_button = node.locator(
                                NavigationPanelLocators.NODE_ROOT
                            ).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
                            toggle_button.click()
                            # Ждем, пока дочерние элементы прогрузятся/появятся
                            page.wait_for_timeout(1000)
                            is_expanded = True

                        # Проверяем, имеет ли узел  дочерние элементы
                        children_count = node.locator('>div.v-treeview-node__children').count()
                        content = node.locator('>div.v-treeview-node__children').inner_html()
                        if children_count > 0 and len(content) != 0:
                            has_children = True

                        # Рекурсивный вызов для дочерних элементов
                        # Ищем дочерние элементы *внутри* текущего узла
                        if has_children and is_expanded:
                            child_nodes_locator = root_locator.locator(
                                f">div:nth-child({index + 1})"
                            ).locator('>div.v-treeview-node__children')
                            found_loc = find_and_click_item(
                                page, child_nodes_locator, item_name, parent=None
                            )
                            if found_loc:
                                if parent is None:
                                    return found_loc
                                else:
                                    root_texts = root_locator.locator(
                                        f">div:nth-child({index + 1})"
                                    ).inner_text().splitlines()
                                    if parent in root_texts:
                                        return found_loc

                        # закрываем узел, если в нем ничего не нашли
                        if is_expanded:
                            toggle_button = node.locator(
                                NavigationPanelLocators.NODE_ROOT
                            ).locator(NavigationPanelLocators.TOGGLE_BUTTON).first
                            toggle_button.click()
                            page.wait_for_timeout(1000)

                # элемент с заданным именем не найден
                return None

            root_locator = self.get_locator(node_root_locator)
            if parent:
                parent_loc = find_and_click_item(self.page, root_locator, parent, parent=None)
                found = find_and_click_item(
                    self.page, parent_loc.locator('>div.v-treeview-node__children'),
                    item_name, parent=None
                )
            else:
                found = find_and_click_item(self.page, root_locator, item_name, parent=None)
            assert found, f"Navigation panel item {item_name} is missing"

        def get_item_names(self, locator: str | Locator) -> list[str]:
            """Возвращает тексты всех элементов по указанному локатору.

            Args:
                locator: Локатор элементов или строка с CSS/XPath.

            Returns:
                Список текстов элементов.
            """

            loc = self.get_locator(locator)
            return loc.all_inner_texts()

        def traverse_panel_tree(self, node_root_locator: str | Locator, level=0, debug=False):
            """
            Рекурсивно обходит дерево v-treeview и выводит информацию об элементах.

            Args:
                node_root_locator: Локатор для поиска корневых элементов дерева.
            """
            def traverse_tree(page, root_locator, level=0, debug=False):
                # Находим все локаторы корневых узлов на текущем уровне
                nodes_count = root_locator.locator('>div.v-treeview-node').count()

                for index in range(nodes_count):
                    node = root_locator.locator(f">div:nth-child({index + 1})").first

                    # Извлекаем текст и аттрибуты из корневого узла
                    node_text = node.inner_text()
                    node_class_attr = node.get_attribute('class')

                    is_expanded = False
                    has_children = False

                    # Проверяем лист это или начало поддерева
                    if "v-treeview-node--leaf" in node_class_attr:
                        if debug:
                            leaf_msg = f'[{level}][{index}] {node_text} (LEAF, Expanded: {is_expanded}'
                            print(f"{leaf_msg}, Has Children: {has_children})")
                            print("-----------------------------------------")
                    else:
                        # Проверяем, является ли узел раскрытым
                        class_attr = node.locator(NavigationPanelLocators.TOGGLE_BUTTON).get_attribute('class')

                        if "v-treeview-node__toggle--open" in class_attr:
                            is_expanded = True

                        # Если узел закрыт можем его раскрыть
                        if is_expanded is False:
                            toggle_button = node.locator(NavigationPanelLocators.TOGGLE_BUTTON)
                            toggle_button.click()
                            # Ждем, пока дочерние элементы прогрузятся/появятся
                            page.wait_for_timeout(300)
                            is_expanded = True

                        # Проверяем, имеет ли узел  дочерние элементы
                        children_count = node.locator('>div.v-treeview-node__children').count()
                        content = node.locator('>div.v-treeview-node__children').inner_html()
                        if children_count > 0 and len(content) != 0:
                            has_children = True

                        edited_node_text = node_text.replace("expand_more\n", "")

                        if debug:
                            # Выводим информацию об узле
                            node_msg = f'[{level}][{index}] {edited_node_text} (NODE, Expanded: {is_expanded}'
                            print(f"{node_msg}, Has Children: {has_children})")
                            print("-----------------------------------------")

                        # Рекурсивный вызов для дочерних элементов
                        # Ищем дочерние элементы *внутри* текущего узла
                        if has_children and is_expanded:
                            child_nodes_locator = root_locator.locator(
                                f">div:nth-child({index + 1})"
                            ).locator('>div.v-treeview-node__children')
                            traverse_tree(page, child_nodes_locator, level+1, debug)

            root_locator = self.get_locator(node_root_locator)
            traverse_tree(self.page, root_locator, level=level, debug=debug)

        # Проверки:

        def check_item_visibility(self, locator: str | Locator, item_name: str) -> None:
            """Проверяет видимость элемента с указанным текстом.

            Args:
                locator: Локатор элемента или строка с CSS/XPath.
                item_name: Текст элемента для проверки.

            Note:
                Временная обработка для элементов с текстом 'Шаблоны'.
            """

            msg = f"Navigation panel item '{item_name}' is not visible"

            ## временно: в навигационной панели есть две панели с именем Шаблоны
            ## для их различия добавлены индексы Шаблоны_1 для Настройки/Шаблоны
            ## Шаблоны_2 для Настройки/ZTP/Шаблоны
            loc = self.get_locator(locator)
            if item_name == "Шаблоны_1":
                loc = loc.get_by_text("Шаблоны").first
            elif item_name == "Шаблоны_2":
                loc = loc.get_by_text("Шаблоны").nth(1)
            else:
                loc = loc.get_by_text(item_name)
            self.check_visibility(loc, msg)

        def is_item_visible(self, locator: str | Locator, item_name: str) -> bool:
            """
            Проверяет видимость элемента с указанным текстом без выбрасывания исключения.

            Args:
                locator: Локатор элемента или строка с CSS/XPath.
                item_name: Текст элемента для проверки.

            Returns:
                bool: True если элемент видим, False если нет.
            """
            element_locator = self.page.locator(locator).filter(has_text=item_name)

            # Сначала проверяем что элемент вообще существует
            if element_locator.count() == 0:
                return False

            return element_locator.is_visible()