# Исходный код components.date_picker_component

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

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

    import datetime
    from playwright.sync_api import Page
    from tools.logger import get_logger
    from locators.date_picker_locators import DatePickerLocators
    from elements.text_element import Text
    from elements.button_element import Button
    from components.base_component import BaseComponent

    logger = get_logger("DATE_PICKER")

    class DatePickerComponent(BaseComponent):
        """Компонент средства выбора даты.

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

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

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

            super().__init__(page)

            self.date_picker_year_button = Button(page,
                                         DatePickerLocators.DATE_PICKER_TITLE_BUTTON_YEAR,
                                         "date_picker_year_button")

            loc = page.locator(DatePickerLocators.DATE_PICKER_HEADER).\
                  get_by_role("button").locator("i.mdi-chevron-left")
            self.prev_month_button = Button(page, loc, "prev_month_button")

            loc = page.locator(DatePickerLocators.DATE_PICKER_HEADER).\
                  get_by_role("button").locator("i.mdi-chevron-right")
            self.next_month_button = Button(page, loc, "next_month_button")

            self.current_month_year = Text(page,
                                         DatePickerLocators.DATE_PICKER_HEADER_VALUE,
                                         "current_month_year")

        # Действия:

        def click_prev_month_button(self) -> None:
            """ Нажатие на кнопку перехода к предыдущему месяцу (стрелочка влево)."""

            self.prev_month_button.click()

        def click_next_month_button(self) -> None:
            """ Нажатие на кнопку перехода к следующему месяцу (стрелочка вправо)."""

            self.next_month_button.click()

        def click_year_button(self) -> None:
            """ Нажатие на кнопку текущего значения года в заголовке средства выбора даты."""

            self.date_picker_year_button.click()

        def get_year(self) -> str:
            """ Получение текущего значения года из заголовка средства выбора даты."""

            return self.date_picker_year_button.get_text(0).strip()

        def get_month_year(self) -> str:
            """ Получение текущего значения месяца и года."""

            return self.current_month_year.get_text(0).strip()

        def get_day(self) -> str:
            """ Получение текущего номера дня."""

            days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS)
            day_button_locator = days_table_locator.locator("//td/button[contains(@class, 'accent--text')]")

            return day_button_locator.text_content().strip()

        def select_day(self, day: str) -> None:
            """ Выбор дня месяца по его номеру."""

            visible = False

            days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS)
            days_table_locator.wait_for(timeout=300)
            day_button_locator = days_table_locator.locator("//td").get_by_role("button", name=day)
            visible = day_button_locator.is_visible()
            if visible:
                day_button_locator.click()
            else:
                assert False, f"Day number {day} is missing on date picker days table"

        def select_year_and_month(self, year: str, month: str) -> None:
            """ Выбор года и месяца по заданным значениям. Значения должны быть в формате гггг и мм"""

            try:
                month_index = int(month)
            except ValueError:
                assert False, f"Incorrect month value {month} for selection"

            assert month_index >= 1, f"Incorrect month value {month} for selection"
            assert month_index <= 12, f"Incorrect month value {month} for selection"

            current_year = int(self.get_year())
            if int(year) > current_year + 100 or int(year) < current_year - 100:
                assert False, f"Incorrect year value {year} for selection"

            self.click_year_button()

            years_list = self.page.locator(DatePickerLocators.DATE_PICKER_LIST_YEARS)
            years_list.wait_for(timeout=300)
            year_locator = f"{DatePickerLocators.DATE_PICKER_LIST_YEARS} li:has-text(\"{year}\")"
            self.page.locator(year_locator).click()

            months_table = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_MONTHS)
            months_table.wait_for(timeout=300)
            month_button = months_table.locator("//td").get_by_role("button").nth(month_index-1)
            month_button.click()

        # Проверки:

        def check_prev_month_button_visibility(self) -> None:
            """ Проверка видимости кнопки перехода к предыдущему месяцу (стрелочка влево)."""

            self.prev_month_button.check_visibility("Prev Month Button is missing")

        def check_next_month_button_visibility(self) -> None:
            """ Проверка видимости кнопки перехода к следующему месяцу (стрелочка вправо)."""

            self.next_month_button.check_visibility("Next Month Button is missing")

        def check_year_button_visibility(self) -> None:
            """ Проверка видимости кнопки текущего значения года в заголовке средства выбора даты."""

            self.date_picker_year_button.check_visibility("Current Year Button is missing")

        def check_content(self) -> None:
            """Проверка состава компонент средства выбора даты."""

            month_dict = {"1":"январь",
                          "2":"февраль",
                          "3":"март",
                          "4":"апрель",
                          "5":"май",
                          "6":"июнь",
                          "7":"июль",
                          "8":"август",
                          "9":"сентябрь",
                          "10":"октябрь",
                          "11":"ноябрь",
                          "12":"декабрь"}
            days_per_month = {"1":31,
                              "2":28,
                              "3":31,
                              "4":30,
                              "5":31,
                              "6":30,
                              "7":31,
                              "8":31,
                              "9":30,
                              "10":31,
                              "11":30,
                              "12":31}
            expected_weekdays = ["В", "П", "В", "С", "Ч", "П", "С"]

            expected_date = datetime.datetime.now()

            # Проверка наличия кнопки текущего значения года в заголовке средства выбора даты
            self.check_year_button_visibility()

            actual_year = self.get_year()
            assert actual_year == str(expected_date.year), \
                f"Expected year {expected_date.year} is not equal actual year {actual_year} on date picker title"

            # Проверка наличия кнопок перехода к предыдущему/следующему месяцу
            self.check_prev_month_button_visibility()
            self.check_next_month_button_visibility()

            # Проверка наличия и правильности текущей даты
            self.current_month_year.check_visibility("Month and Year values is missing on date picker body")

            y = expected_date.year
            m = str(expected_date.strftime("%m"))
            expected_month_year = f"{month_dict[m]} {y} г."
            actual_month_year = self.get_month_year()
            assert actual_month_year == expected_month_year, \
                f"Expected value {expected_month_year} is not equal actual value {actual_month_year} on date picker body"

            expected_day = str(expected_date.strftime("%d"))
            actual_day = self.get_day()
            assert actual_day == expected_day, \
                f"Expected day {expected_day} is not equal actual day {actual_day} on date picker body"

            # Проверка таблицы дней
            days_table_locator = self.page.locator(DatePickerLocators.DATE_PICKER_TABLE_DAYS)
            headers = days_table_locator.locator("th").all()
            actual_weekdays = []
            for header in headers:
                actual_weekdays.append(header.text_content())

            assert actual_weekdays == expected_weekdays, \
                f"Expected weekdays list {expected_weekdays} is not equal actual weekdays list {actual_weekdays} on date picker body"

            rows = days_table_locator.locator("//tbody/tr")
            days_counter = 0
            for i in range(rows.count()):
                row = rows.nth(i)
                cells = row.locator("td")
                for j in range(cells.count()):
                    cell_text = cells.nth(j).inner_text()
                    if cell_text != "":
                        days_counter += 1

            expected_day_counter = days_per_month[m]
            if m == "2" and self._is_leap_year(expected_date.year):
                expected_day_counter = 29

            assert days_counter == expected_day_counter, f"Incorrect amount of days {days_counter} on date picker body"

        def _is_leap_year(self, year: str) -> bool:
            """Проверка является ли год високосным."""

            if int(year) % 400 == 0:
                return True
            if int(year) % 100 == 0:
                return False
            if int(year) % 4 == 0:
                return True
            return False