"""Модуль компонента панели выбора значения.

Содержит класс для работы с компонентом панели выбора значения через Playwright.
"""

from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from locators.selection_bar_locators import SelectionBarLocators
from locators.combobox_locators import ComboboxLocators
from components.dropdown_list_component import DropdownList
from components.base_component import BaseComponent

logger = get_logger("SELECTION_BAR")


class SelectionBarComponent(BaseComponent):
    """Компонент панели выбора значения.

    Предоставляет методы для взаимодействия с элементами компонента панели выбора значения.
    """

    def __init__(self, page: Page, locator_or_text: str | Locator) -> None:
        """Инициализирует компонент панели выбора значения.

        Args:
            page: Экземпляр страницы Playwright.
            locator_or_text: Локатор панели выбора значения (строка или объект Locator)
                            или текст для поиска
        """
        super().__init__(page)

        # Определяем локатор в зависимости от типа параметра
        if isinstance(locator_or_text, Locator):
            # Если передан готовый Locator
            self.selection_bar_locator = locator_or_text
        elif locator_or_text.startswith(('//', '.', '#', 'xpath=', 'css=')):
            # Если передан строковый локатор
            self.selection_bar_locator = self.get_locator(locator_or_text)
        else:
            # Если передан текст - ищем по тексту label
            xpath = SelectionBarLocators.COMBOBOX_BY_LABEL_XPATH.format(locator_or_text)
            self.selection_bar_locator = self.page.locator(xpath)

        # При нажатии на панель появляется выпадающий список с параметрами фильтрации для выбора
        self.selected_values_list = DropdownList(self.page)

    # Действия:
    def clear_selections(self) -> None:
        """Удаление ранее выбранных значений"""
        selected_values = self.get_selected_values()
        if len(selected_values) > 0:
            clear_button_locator = self.selection_bar_locator.locator(
                SelectionBarLocators.CLEAR_SELECTION_BUTTON
            )
            clear_button_locator.click()

    def get_available_options(self) -> list[str]:
        """Возвращает список всех доступных опций из выпадающего списка.

        Returns:
            list[str]: Список доступных опций
        """
        logger.info("Getting available options from dropdown list...")

        # Открываем выпадающий список
        self.open_values_list()

        # Ждем появления списка
        self.wait_for_timeout(1000)

        # Получаем все элементы списка
        options = self.selected_values_list.get_item_names(
            SelectionBarLocators.LIST_ITEMS
        )

        # Закрываем список (кликаем вне его)
        self.page.mouse.click(10, 10)
        self.wait_for_timeout(500)

        logger.info(f"Found available options: {len(options)} - {options}")
        return options

    def get_selection_bar_title(self) -> str:
        """Возвращает название панели выбора значения"""
        title_locator = self.selection_bar_locator.locator(SelectionBarLocators.TITLE_LOCATOR)
        return title_locator.text_content()

    def get_selected_values(self) -> list[str]:
        """Возвращает список выбранных значений"""
        selected_values_locator = self.selection_bar_locator.locator(
            SelectionBarLocators.PARAMETERS_SELECTED
        )
        selected_values = selected_values_locator.all_inner_texts()
        return selected_values[0].splitlines()

    def clear_combobox_field(self, field_name: str, field_locator: str) -> None:
        """Очищает значение в combobox поле с помощью кнопки закрытия (крестика).

        Args:
            field_name: Название поля для очистки
            field_locator: Локатор поля combobox
        """
        logger.info(f"Clearing combobox field '{field_name}' using close button...")

        # Находим поле по локатору
        field_container = self.page.locator(field_locator).first

        # Проверяем что поле видимо
        if not field_container.is_visible():
            logger.info(f"Field '{field_name}' is not visible, skipping clearing")
            return

        # Прокручиваем до поля
        field_container.scroll_into_view_if_needed()
        self.wait_for_timeout(500)

        # Ищем кнопку закрытия (крестик) внутри контейнера поля
        close_button = field_container.locator(
            ComboboxLocators.COMBOBOX_CLOSE_BUTTON
        )

        # Проверяем наличие и видимость кнопки закрытия
        if close_button.count() > 0 and close_button.is_visible():
            # Если кнопка закрытия видима - кликаем на нее
            close_button.click()
            self.wait_for_timeout(500)
            logger.info(f"Combobox field '{field_name}' cleared using close button")
        else:
            # Если кнопки закрытия нет, просто логируем этот факт
            msg = f"Close button not found for field '{field_name}', clearing not performed"
            logger.info(msg)

    def open_values_list(self) -> None:
        """Открытие выпадающего списка путем нажатия на панель выбора значения"""
        expect(self.selection_bar_locator).to_be_visible()

        # Проверяем, не открыт ли уже список
        parent_class = self.selection_bar_locator.get_attribute("class")
        if parent_class and SelectionBarLocators.MENU_ACTIVE_CLASS in parent_class:
            logger.info("Values list is already open")
            return

        # Используем force click для обхода перекрывающих элементов
        logger.info("Using force click to open the list")
        self.selection_bar_locator.click(force=True)

        # Ждем появления выпадающего списка
        self.wait_for_timeout(1500)

    def select_value(self, name: str) -> None:
        """Выбор значения из списка"""
        self.selected_values_list.check_item_with_text(name)
        self.selected_values_list.click_item_with_text(name)

    def wait_for_timeout(self, timeout: int) -> None:
        """Ожидает указанное количество миллисекунд.

        Args:
            timeout: Время ожидания в миллисекундах
        """
        self.page.wait_for_timeout(timeout)

    # Проверки:

    def check_field_highlighted_error(self, field_name: str, field_locator: str) -> None:
        """Проверяет, что поле подсвечено цветом ошибки (валидация не пройдена).

        Args:
            field_name: Название поля для проверки
            field_locator: Локатор поля для проверки
        """
        logger.info(f"Checking field '{field_name}' for error highlighting...")

        field_element = self.page.locator(field_locator).first

        # Проверяем что поле видимо
        self.check_visibility(field_element, f"Field '{field_name}' not found")

        # Ищем родительский контейнер
        parent_container = field_element.locator(SelectionBarLocators.INPUT_PARENT_CONTAINER).first

        # Проверка классов ошибки с использованием локатора из SelectionBarLocators
        if parent_container.count() > 0:
            has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0

            if not has_error:
                raise AssertionError(f"Field '{field_name}' is not highlighted with error color")

        logger.info(f"Field '{field_name}' is correctly highlighted with error color")

    def check_field_not_highlighted_error(self, field_name: str, field_locator: str) -> None:
        """Проверяет, что поле НЕ подсвечено цветом ошибки (валидация успешна).

        Args:
            field_name: Название поля для проверки
            field_locator: Локатор поля для проверки
        """
        logger.info(f"Checking field '{field_name}' for absence of error highlighting...")

        field_element = self.page.locator(field_locator).first

        # Проверяем что поле видимо
        self.check_visibility(field_element, f"Field '{field_name}' not found")

        # Ищем родительский контейнер
        parent_container = field_element.locator(SelectionBarLocators.INPUT_PARENT_CONTAINER).first

        # Проверяем отсутствие классов ошибки с использованием локатора из SelectionBarLocators
        if parent_container.count() > 0:
            has_error = parent_container.locator(SelectionBarLocators.ERROR_CSS_SELECTORS).count() > 0

            if has_error:
                raise AssertionError(f"Field '{field_name}' is highlighted with error")

        logger.info(f"Field '{field_name}' correctly has no error highlighting")
