"""Модуль вкладки 'Шаблоны'.

Содержит класс TemplatesTab для работы с таблицей шаблонов.
Позволяет проверять состояние и взаимодействовать с элементами вкладки.
"""

from playwright.sync_api import Page
from tools.logger import get_logger
from locators.table_locators import TableLocators
from locators.modal_window_locators import ModalWindowLocators
from components_derived.modal_view_template import ViewTemplateModalWindow
from components.modal_window_component import ModalWindowComponent
from components.toolbar_component import ToolbarComponent
from components.table_component import TableComponent
from pages.base_page import BasePage

logger = get_logger("TEMPLATES_TAB")


class TemplatesTab(BasePage):
    """Класс для работы с вкладкой 'Шаблоны'.

    Предоставляет методы для взаимодействия с таблицей шаблонов и проверки
    её состояния.

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

    def __init__(self, page: Page) -> None:
        """Инициализирует компоненты вкладки 'Шаблоны'."""

        super().__init__(page)

        self.toolbar = ToolbarComponent(page, "Шаблоны")

        self.templates_table = TableComponent(page)
        self.modal_windows = {}

    def add_modal_window(self, title: str) -> None:
        """Добавляет модальное окно в коллекцию.

        Args:
            title: Заголовок окна.
        """

        self.modal_windows[title] = ViewTemplateModalWindow(self.page, title)

    def get_modal_window(self, title: str) -> ViewTemplateModalWindow:
        """Возвращает модальное окно по заголовку.

        Args:
            title: Заголовок окна.

        Returns:
            ViewTemplateModalWindow: Экземпляр модального окна.

        Raises:
            AssertionError: Если окно не найдено.
        """

        modal_window = self.modal_windows.get(title)

        if modal_window is None:
            assert False, f"Modal window with title '{title}' not found"
        return modal_window

    def delete_modal_window(self, title: str) -> None:
        """Удаляет модальное окно из коллекции.

        Args:
            title: Заголовок окна.

        Raises:
            AssertionError: Если окно не найдено.
        """

        if self.modal_windows.get(title) is None:
            assert False, f"Modal window with title '{title}' not found"
        self.modal_windows[title] = None

    def open_template_modal_by_index(self, row_index: int = 0) -> str:
        """Открывает модальное окно шаблона по клику на строку таблицы.

        Args:
            row_index: Индекс строки для клика (по умолчанию 0 - первая строка).

        Returns:
            str: Имя шаблона.
        """
        row_locator = self.templates_table.get_row_locator(
            TableLocators.TABLE_WORK_AREA,
            row_index
        )
        row_locator.click()

        # Получаем имя шаблона из выбранной строки
        table_content = self.templates_table.read(TableLocators.TABLE_WORK_AREA)
        # +1 потому что первая строка - заголовки
        title = table_content[row_index + 1][0]

        # Добавляем модальное окно в коллекцию после открытия
        self.add_modal_window(title)

        return title

    def close_modal_window_by_toolbar_button(self, title: str) -> None:
        """Закрывает модальное окно через кнопку в тулбаре.

        Args:
            title: Заголовок окна.
        """

        modal_window = self.get_modal_window(title)
        modal_window.close_window_by_toolbar_button()
        self.delete_modal_window(title)

    def get_rows_count(self) -> int:
        """Возвращает количество строк в таблице (без заголовка).

        Returns:
            int: Количество строк с данными.

        Raises:
            AssertionError: Если таблица пуста.
        """

        return self.templates_table.get_rows_count(TableLocators.TABLE_WORK_AREA)

    def scroll_templates_table_up(self) -> None:
        """Прокручивает таблицу шаблонов вверх."""

        self.templates_table.scroll_up(TableLocators.TABLE_SCROLL_CONTAINER)

    def scroll_templates_table_down(self) -> None:
        """Прокручивает таблицу шаблонов вниз."""

        self.templates_table.scroll_down(TableLocators.TABLE_SCROLL_CONTAINER)

    def scroll_modal_up(self) -> None:
        """Прокручивает содержимое модального окна вверх."""

        temp_modal = ModalWindowComponent(self.page)
        temp_modal.scroll_window_up()

    def scroll_modal_down(self) -> None:
        """Прокручивает содержимое модального окна вниз."""

        temp_modal = ModalWindowComponent(self.page)
        temp_modal.scroll_window_down()

    def extract_specific_template(self, title: str, response_data: dict) -> dict:
        """Извлекает структуру конкретного шаблона по title из данных API.

        Args:
            title: Имя шаблона для извлечения.
            response_data: Данные ответа от API.

        Returns:
            dict: Структура конкретного шаблона.

        Raises:
            AssertionError: Если шаблон с указанным именем не найден
                или структура ответа некорректна.
        """
        # Проверяем, что ответ является списком шаблонов
        assert isinstance(response_data, list), "API response is not a list of templates"

        # Ищем шаблон с указанным именем
        for template in response_data:
            if template.get('id') == title:
                logger.info("Found template: %s", title)
                return template

        # Если шаблон не найден
        available_templates = [t.get('id', 'Unknown') for t in response_data]

        # Генерируем понятное сообщение об ошибке
        error_msg = (
            f"Template '{title}' not found. "
            f"Available templates: {available_templates}"
        )
        logger.error(error_msg)
        assert False, error_msg

    def get_template_data_from_api(self, title: str) -> dict:
        """Получает данные шаблона из API.

        Args:
            title: Имя шаблона.

        Returns:
            dict: Данные шаблона из API.
        """
        # Отправляем запрос к backend для получения информации о шаблоне
        response = self.send_get_api_request("e-cmdb/api/device/template")
        response_body = self.get_response_body(response)

        # Извлекаем конкретный шаблон по имени из ответа API
        template_data = self.extract_specific_template(title, response_body)
        return template_data

    def verify_json_container_content(self, title: str) -> None:
        """Проверяет соответствие данных контейнера данным из API.

        Args:
            title: Имя шаблона для проверки.
        """
        # Получаем данные шаблона из API
        template_data = self.get_template_data_from_api(title)

        # Получаем модальное окно и проверяем содержимое JSON контейнера
        modal_window = self.get_modal_window(title)
        modal_window.verify_json_container_content(template_data)

    def check_templates_modal_content(self, title: str) -> None:
        """Проверяет наличие и корректность элементов модального окна шаблона.

        Args:
            title: Имя шаблона для проверки заголовка окна.

        Raises:
            AssertionError: Если элементы окна некорректны.
        """
        modal_window = self.get_modal_window(title)
        modal_window.check_content()

    def check_templates_table_content(self) -> None:
        """Проверяет содержимое таблицы шаблонов.

        Проверяет заголовки и наличие данных в таблице.

        Raises:
            AssertionError: Если таблица пуста или заголовки неверны.
        """

        expected_headers = [
            'Имя',
            'Описание',
            'Тип устройства',
            'Производитель'
        ]

        self.templates_table.check_content(TableLocators.TABLE_WORK_AREA, expected_headers)

    def check_templates_table_vertical_scrolling(self) -> bool:
        """Проверяет возможность вертикальной прокрутки таблицы.

        Returns:
            bool: True если прокрутка возможна, иначе False.
        """

        return self.templates_table.is_scrollable_vertically(
            TableLocators.TABLE_SCROLL_CONTAINER
        )

    def check_templates_table_first_row_visibility(self) -> None:
        """Проверяет видимость первой строки таблицы.

        Raises:
            AssertionError: Если строка не видна.
        """

        self.templates_table.check_first_row_visibility(TableLocators.TABLE_WORK_AREA)

    def check_templates_table_last_row_visibility(self) -> None:
        """Проверяет видимость последней строки таблицы.

        Raises:
            AssertionError: Если строка не видна.
        """

        self.templates_table.check_last_row_visibility(TableLocators.TABLE_WORK_AREA)

    def check_templates_table_row_highlighting(self, row_index: int) -> None:
        """Проверяет выделение указанной строки таблицы.

        Args:
            row_index: Индекс проверяемой строки.

        Raises:
            AssertionError: Если строка не выделена.
        """

        self.templates_table.check_row_highlighting(
            TableLocators.TABLE_WORK_AREA,
            row_index
        )

    def should_be_toolbar(self) -> None:
        """Проверяет наличие тулбара на вкладке.

        Raises:
            AssertionError: Если тулбар отсутствует.
        """

        self.toolbar.check_toolbar_presence("Toolbar is missing")

    def should_be_templates_table(self) -> None:
        """Проверяет наличие таблицы шаблонов.

        Raises:
            AssertionError: Если таблица отсутствует.
        """

        self.templates_table.check_visibility(
            TableLocators.TABLE_WORK_AREA,
            "Templates table is missing"
        )

    def should_be_modal_window(self) -> None:
        """Проверяет наличие модального окна.

        Raises:
            AssertionError: Если модальное окно отсутствует.
        """
        self.templates_table.check_visibility(
            ModalWindowLocators.MODAL_WINDOW,
            "Modal window is not visible"
        )

    def should_not_be_modal_window(self) -> None:
        """Проверяет, что модальное окно отсутствует.

        Raises:
            AssertionError: Если модальное окно все еще видно.
        """
        is_visible = self.page.locator(
            ModalWindowLocators.MODAL_WINDOW
        ).is_visible(timeout=1000)
        if is_visible:
            assert False, "Modal window should not be visible"

    def check_modal_vertical_scrolling(self) -> bool:
        """Проверяет возможность вертикального скроллинга в модальном окне.

        Returns:
            bool: True если скроллинг возможен, иначе False.
        """
        temp_modal = ModalWindowComponent(self.page)
        return temp_modal.check_window_vertical_scrolling()
