"""Модуль компонента группы чек-боксов.

Содержит класс CheckboxGroupComponent для работы с группами чек-боксов,
в том числе в выпадающих списках с множественным выбором.
"""

import re
from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger
from components.base_component import BaseComponent

logger = get_logger("CHECKBOX_GROUP_COMPONENT")

class CheckboxGroupComponent(BaseComponent):
    """Компонент для работы с группами чек-боксов.

    Позволяет выбирать/снимать выбор с чек-боксов в группе,
    получать список выбранных элементов и проверять их состояние.
    Может использоваться как для выпадающих списков с множественным выбором,
    так и для любых других групп чек-боксов на странице.
    """

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

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

    def get_checkbox_locator(self, text: str, container_locator: Locator | None = None) -> Locator:
        """Возвращает локатор чек-бокса с указанным текстом.

        Args:
            text (str): Текст элемента для выбора.
            container_locator (Locator | None): Локатор контейнера с чек-боксами.
                                               Если не указан, поиск по всей странице.

        Returns:
            Locator: Локатор чек-бокса.
        """
        if container_locator:
            checkbox_locator = container_locator.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox")
        else:
            checkbox_locator = self.page.get_by_role("listitem").filter(has_text=text).get_by_role("checkbox")

        if checkbox_locator.count() > 1:
            rtext = f"^{text}$"
            if container_locator:
                checkbox_locator = container_locator.get_by_role("listitem").filter(
                    has_text=re.compile(rtext)
                ).get_by_role("checkbox")
            else:
                checkbox_locator = self.page.get_by_role("listitem").filter(
                    has_text=re.compile(rtext)
                ).get_by_role("checkbox")

        expect(checkbox_locator).to_be_visible(), \
            f"Checkbox with text '{text}' is missing or not visible"
        return checkbox_locator

    def uncheck_by_text(self, text: str, container_locator: Locator | None = None) -> None:
        """Снимает выбор с чек-бокса по указанному тексту.

        Args:
            text (str): Текст чек-бокса для снятия выбора.
            container_locator (Locator | None): Локатор контейнера с чек-боксами.
        """
        logger.info(f"Unchecking checkbox with text: {text}")
        self.get_checkbox_locator(text, container_locator).uncheck(force=True)

    def check_by_text(self, text: str, container_locator: Locator | None = None) -> None:
        """Выбирает чек-бокс по указанному тексту.

        Args:
            text (str): Текст чек-бокса для выбора.
            container_locator (Locator | None): Локатор контейнера с чек-боксами.
        """
        logger.info(f"Checking checkbox with text: {text}")
        self.get_checkbox_locator(text, container_locator).check(force=True)

    def get_checked_items(self, container_locator: str | Locator) -> list[str]:
        """Возвращает список текстов отмеченных чек-боксов.

        Args:
            container_locator (str | Locator): Локатор контейнера с группой чек-боксов.

        Returns:
            list[str]: Список текстов выбранных чек-боксов.
        """
        checked_items = []
        list_container = self.get_locator(container_locator)
        items = list_container.get_by_role("listitem").all()

        for item in items:
            if item.get_by_role("checkbox").is_checked():
                item_text = item.text_content().strip()
                if item_text:
                    checked_items.append(item_text)

        logger.info(f"Checked items: {checked_items}")
        return checked_items

    def are_items_checked(self, container_locator: str | Locator, expected_items: list[str]) -> bool:
        """Проверяет, что указанные чек-боксы выбраны.

        Args:
            container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
            expected_items (list[str]): Список ожидаемых выбранных элементов.

        Returns:
            bool: True если все указанные чек-боксы выбраны.
        """
        checked_items = self.get_checked_items(container_locator)
        return all(item in checked_items for item in expected_items)

    def check_all(self, container_locator: str | Locator) -> None:
        """Выбирает все чек-боксы в группе.

        Args:
            container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
        """
        logger.info("Checking all checkboxes in group")
        list_container = self.get_locator(container_locator)
        checkboxes = list_container.get_by_role("checkbox").all()

        for checkbox in checkboxes:
            if not checkbox.is_checked():
                checkbox.check(force=True)

    def uncheck_all(self, container_locator: str | Locator) -> None:
        """Снимает выбор со всех чек-боксов в группе.

        Args:
            container_locator (str | Locator): Локатор контейнера с группой чек-боксов.
        """
        logger.info("Unchecking all checkboxes in group")
        list_container = self.get_locator(container_locator)
        checkboxes = list_container.get_by_role("checkbox").all()

        for checkbox in checkboxes:
            if checkbox.is_checked():
                checkbox.uncheck(force=True)

    def get_items_count(self, container_locator: str | Locator) -> int:
        """Возвращает количество чек-боксов в группе.

        Args:
            container_locator (str | Locator): Локатор контейнера с группой чек-боксов.

        Returns:
            int: Количество чек-боксов.
        """
        list_container = self.get_locator(container_locator)
        return list_container.get_by_role("checkbox").count()
