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

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()
                        node_texts = node_text.splitlines()
                        if len(node_texts) > 1:
                            node_text = node_texts[1]
                        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()
