"""Базовый модуль для работы с компонентами страницы.

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

from playwright.sync_api import Page, Locator, expect
from tools.logger import get_logger

logger = get_logger("BASE_COMPONENT")


class BaseComponent:
    """Базовый компонент для работы с элементами страницы.

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

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

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

        self.page = page

    # Действия:
    def get_locator(self, locator: str | Locator) -> Locator:
        """Получение объекта Locator из строки или существующего Locator.

        Args:
            locator: строка с CSS/XPath селектором или объект Locator.

        Returns:
            Locator: объект для работы с элементом.

        Raises:
            TypeError: если передан некорректный тип локатора.
        """

        if isinstance(locator, Locator):
            return locator
        elif isinstance(locator, str):
            return self.page.locator(locator)
        else:
            raise TypeError("locator value should be string type or Locator type")

    # Закомментированный код сохранен без изменений
    # def wait_for_all_elements(self, locator: Locator, timeout=5000):
    #     loc = self.get_locator(locator)
    #     elements = self.page.locator(loc).all()
    #
    #     for element in elements:
    #         self.page.locator(loc).wait_for(timeout=timeout)
    #
    #     return elements

    # Проверки:
    def check_presence(self, locator: str | Locator, msg: str) -> None:
        """Проверка видимости элемента на странице.

        Args:
            locator: локатор элемента (строка или объект Locator).
            msg: сообщение об ошибке при неудачной проверке.

        Raises:
            AssertionError: если элемент не виден на странице.
        """

        loc = self.get_locator(locator)
        expect(loc).to_be_visible(visible=True, timeout=12000), msg

    def is_scrollable_vertically(self, locator: str | Locator) -> bool:
        """Проверка возможности вертикальной прокрутки элемента.

        Args:
            locator: локатор элемента.

        Returns:
            bool: True если элемент можно прокрутить вертикально.
        """

        loc = self.get_locator(locator)
        return loc.evaluate("el => el.scrollHeight > el.clientHeight")

    def is_scrollable_horizontally(self, locator: str | Locator) -> bool:
        """Проверка возможности горизонтальной прокрутки элемента.

        Args:
            locator: локатор элемента.

        Returns:
            bool: True если элемент можно прокрутить горизонтально.
        """

        loc = self.get_locator(locator)
        return loc.evaluate("el => el.scrollWidth > el.clientWidth")

    # Методы прокрутки:
    def scroll_up(self, locator: str | Locator) -> None:
        """Прокрутка элемента вверх.

        Args:
            locator: локатор элемента.

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

        loc = self.get_locator(locator)
        loc.evaluate("el => el.scrollTo(0, 0)")
        loc.wait_for(timeout=2000)

        # Проверка позиции прокрутки
        scroll_position = loc.evaluate("el => el.scrollTop")
        assert scroll_position == 0, "Invalid postion after scroll up"

    def scroll_down(self, locator: str | Locator) -> None:
        """Прокрутка элемента вниз.

        Args:
            locator: локатор элемента.

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

        loc = self.get_locator(locator)
        loc.evaluate("el => el.scrollTo(0, el.scrollHeight)")
        loc.wait_for(timeout=2000)

        # Проверка позиции прокрутки
        scroll_position = loc.evaluate("el => el.scrollTop")
        assert scroll_position > 0, "Invalid postion after scroll down"

    def scroll_left(self, locator: str | Locator) -> None:
        """Прокрутка элемента влево.

        Args:
            locator: локатор элемента.

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

        loc = self.get_locator(locator)

        loc.evaluate("el => el.scrollBy(-el.scrollWidth, 0)")

        loc.wait_for(timeout=2000)

        # Проверка позиции прокрутки
        scroll_position = loc.evaluate("el => el.scrollLeft")
        assert scroll_position == 0, "Invalid postion after scroll left"

    def scroll_right(self, locator: str | Locator) -> None:
        """Прокрутка элемента вправо.

        Args:
            locator: локатор элемента.

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

        loc = self.get_locator(locator)

        loc.evaluate("el => el.scrollBy(el.scrollWidth, 0)")     

        loc.wait_for(timeout=2000)

        # Проверка позиции прокрутки
        scroll_position = loc.evaluate("el => el.scrollLeft")
        max_scroll_x = loc.evaluate("el => el.scrollWidth - el.clientWidth")
        assert scroll_position >= max_scroll_x, "Invalid postion after scroll right"
