"""Тест создания дочернего элемента 'Стойка'."""

import pytest
from playwright.sync_api import Page
from tools.logger import get_logger
from locators.navigation_panel_locators import NavigationPanelLocators
from components_derived.accounting_objects.rack_maker import RackObjectMaker, RackData
from components_derived.frames.create_child_element_frame import CreateChildElementFrame
from pages.location_page import LocationPage
from pages.login_page import LoginPage
from pages.main_page import MainPage


logger = get_logger("CREATE_RACK_ELEMENT_TEST")

# @pytest.mark.smoke
class TestCreateRackElement:
    """Тест создания дочернего элемента типа 'Стойка'.

    Тесты покрывают следующие сценарии:
    1. test_create_rack_content: Проверяет содержимое формы создания стойки
    2. test_create_rack_child_element: Проверяет создание дочернего элемента типа 'Стойка'
    3. test_create_rack_with_duplicate_name: Проверяет создание стойки с дублирующимся именем
    4. test_required_fields_validation: Проверяет валидацию обязательных полей при создании стойки
    """

    @pytest.fixture(scope="function", autouse=True)
    def setup(self, browser: Page) -> None:
        """Фикстура для подготовки тестового окружения.

        Args:
            browser (Page): Экземпляр страницы Playwright для взаимодействия с UI
        """
        # Авторизация в системе
        login_page = LoginPage(browser)
        login_page.do_login()

        # Мы на главной странице
        self.main_page = MainPage(browser)
        self.main_page.should_be_navigation_panel()
        self.main_page.wait_for_timeout(2000)

        # Переходим к Объектам
        self.main_page.click_main_navigation_panel_item("Объекты")
        self.main_page.wait_for_timeout(2000)

        self.main_page.click_main_navigation_panel_item("test-zone")
        self.main_page.wait_for_timeout(2000)

        # Создаем экземпляр страницы локации
        self.location_page = LocationPage(browser)

    @pytest.mark.develop
    def test_create_rack_content(self, browser: Page) -> None:
        """Тест создания дочернего элемента типа 'Стойка'."""

        # Проверяем что кнопка "Создать" доступна
        self.location_page.should_be_toolbar_buttons()

        # Нажимаем кнопку "Создать" на тулбаре
        self.location_page.click_create_button()

        # Создаем фрейм создания дочернего элемента
        create_child_frame = CreateChildElementFrame(browser)

        # Нажимаем на плашку "Класс объекта учета"
        create_child_frame.open_object_class_combobox()

        # Из выпадающего меню выбираем пункт "Стойка"
        create_child_frame.select_object_class("Стойка")

        # Открывается набор плашек для задания параметров стойки
        rack_maker = RackObjectMaker(browser)

        # Проверяем заголовок формы создания
        create_child_frame.check_toolbar_title('Создать дочерний элемент в')

        # Проверяем что после выбора 'Стойка' появляются специфичные поля
        rack_maker.check_rack_fields_presence()
        logger.info("Rack-specific fields are displayed correctly")

        create_child_frame.should_be_toolbar_buttons()

    def test_create_rack_child_element(self, browser: Page) -> None:
        """Тест создания дочернего элемента типа 'Стойка'."""

        # Нажимаем кнопку "Создать" на тулбаре
        self.location_page.click_create_button()

        # Создаем фрейм создания дочернего элемента
        create_child_frame = CreateChildElementFrame(browser)

        # Нажимаем на плашку "Класс объекта учета"
        create_child_frame.open_object_class_combobox()

        # Из выпадающего меню выбираем пункт "Стойка"
        create_child_frame.select_object_class("Стойка")

        # Открывается набор плашек для задания параметров стойки
        rack_maker = RackObjectMaker(browser)

        # Проверяем что после выбора 'Стойка' появляются специфичные поля
        rack_maker.check_rack_fields_presence()
        logger.info("Rack-specific fields are displayed correctly")

        # Создаем объект данных стойки
        rack_data = RackData(
            name="Test-Rack-01",
            height="42",
            depth="1000",
            serial="TEST123456",
            inventory="INV-001",
            comment="Тестовая стойка для автоматизации",
            cable_entry="Сверху",
            state="В эксплуатации"
        )

        # Заполняем данные стойки
        rack_maker.fill_rack_data(rack_data)

        # Нажимаем кнопку "Добавить"
        create_child_frame.click_add_button()
        create_child_frame.wait_for_timeout(2000)

        logger.info("Test for creating 'Rack' child element completed successfully")

    def test_create_rack_with_duplicate_name(self, browser: Page) -> None:
        """
        Тест создания стойки с уже существующим именем.

        Проверяет, что система корректно обрабатывает попытку создания
        стойки с именем, которое уже используется.
        """
        logger.info("Starting test for creating rack with duplicate name")

        rack_name = "Test-Rack-01"

        # Проверяем, существует ли уже стойка с таким именем
        if not self._check_rack_exists(browser, rack_name):
            logger.info(f"Rack with name '{rack_name}' not found. Creating first rack.")
            self._create_rack(browser, rack_name)
            logger.info(f"First rack with name '{rack_name}' created successfully")
        else:
            logger.info(f"Rack with name '{rack_name}' already exists, proceeding to create second one")

        # Создаем вторую стойку с тем же именем
        logger.info(f"Attempting to create second rack with name '{rack_name}'")

        # Переходим обратно к созданию новой стойки
        self.main_page.click_main_navigation_panel_item("test-zone")
        self.main_page.wait_for_timeout(2000)

        # Нажимаем кнопку "Создать" на тулбаре
        self.location_page.click_create_button()

        # Создаем фрейм создания дочернего элемента
        create_child_frame = CreateChildElementFrame(browser)

        # Нажимаем на плашку "Класс объекта учета"
        create_child_frame.open_object_class_combobox()

        # Из выпадающего меню выбираем пункт "Стойка"
        create_child_frame.select_object_class("Стойка")

        # Открывается набор плашек для задания параметров стойки
        rack_maker = RackObjectMaker(browser)

        # Создаем объект данных для второй стойки
        rack_data = RackData(
            name=rack_name,
            height="42",
            depth="1000"
        )

        # Пытаемся создать вторую стойку с тем же именем
        rack_maker.fill_rack_data(rack_data)

        # Нажимаем кнопку создания
        create_child_frame.click_add_button()
        create_child_frame.wait_for_timeout(2000)

        # Проверяем наличие alert-окна с сообщением о дублирующемся имени
        expected_alert_text = f"Имя {rack_name} уже используется"
        create_child_frame.alert.check_alert_presence(expected_alert_text)

        # Проверяем, что остались на странице создания (стойка не создана)
        create_child_frame.check_toolbar_title('Создать дочерний элемент в')

        # Закрываем alert-окно с помощью кнопки закрытия
        create_child_frame.wait_for_timeout(2000)
        create_child_frame.alert.close_alert_by_text(expected_alert_text)

        logger.info("System prevented creating rack with duplicate name")

    def _perform_required_fields_test(self, create_child_frame, rack_maker, test_data):
        """Выполняет один тест валидации обязательных полей.

        Args:
            create_child_frame: Фрейм создания дочернего элемента
            rack_maker: Объект для работы со стойкой
            test_data: Словарь с данными теста
        """
        # Распаковываем данные теста
        name_value = test_data["name"]
        height_value = test_data["height"]
        depth_value = test_data["depth"]
        expected_alert_height = test_data["expected_alert_height"]
        expected_alert_depth = test_data["expected_alert_depth"]

        # Очистить поля
        create_child_frame.clear_combobox_field("Глубина (мм)")
        create_child_frame.clear_combobox_field("Высота в юнитах")

        # Создаем объект данных стойки
        rack_data = RackData(
            name=name_value,
            height=height_value,
            depth=depth_value
        )

        # Заполняем данные
        rack_maker.fill_rack_data(rack_data)

        # Нажимаем кнопку создания
        create_child_frame.click_add_button()
        create_child_frame.wait_for_timeout(3000)

        # Проверяем подсветку полей
        if height_value:
            create_child_frame.check_field_not_highlighted_error("Высота в юнитах")
        else:
            create_child_frame.check_field_highlighted_error("Высота в юнитах")

        if depth_value:
            create_child_frame.check_field_not_highlighted_error("Глубина (мм)")
        else:
            create_child_frame.check_field_highlighted_error("Глубина (мм)")

        # Обрабатываем alert-окна
        if not height_value:
            create_child_frame.alert.check_alert_presence(expected_alert_height)
            create_child_frame.alert.close_alert_by_text(expected_alert_height)

        if not depth_value:
            create_child_frame.alert.check_alert_presence(expected_alert_depth)
            create_child_frame.alert.close_alert_by_text(expected_alert_depth)

        # Проверяем, что остались на той же странице
        create_child_frame.check_toolbar_title('Создать дочерний элемент в')

    def test_required_fields_validation(self, browser: Page) -> None:
        """
        Тест проверки обязательных полей при создании стойки.

        Проверяет, что система корректно валидирует обязательные поля:
        - Поле 'Высота в юнитах' должно быть заполнено
        - Поле 'Глубина (мм)' должно быть заполнено
        """
        # Текст сообщения alert-окна
        expected_alert_text_height = "поле Высота в юнитах должно быть заполнено"
        expected_alert_text_depth = "поле Глубина (мм) должно быть заполнено"

        # Нажимаем кнопку "Создать" на тулбаре
        self.location_page.click_create_button()

        # Создаем фрейм создания дочернего элемента
        create_child_frame = CreateChildElementFrame(browser)

        # Нажимаем на плашку "Класс объекта учета"
        create_child_frame.open_object_class_combobox()

        # Из выпадающего меню выбираем пункт "Стойка"
        create_child_frame.select_object_class("Стойка")

        # Открывается набор плашек для задания параметров стойки
        rack_maker = RackObjectMaker(browser)

        # Проверяем наличие полей стойки
        rack_maker.check_rack_fields_presence()

        # Тестовые данные
        test_cases = [
            {
                "name": "Test 1: Creating rack with default field values",
                "data": {
                    "name": "",
                    "height": "",
                    "depth": "",
                    "expected_alert_height": expected_alert_text_height,
                    "expected_alert_depth": expected_alert_text_depth
                }
            },
            {
                "name": "Test 2: Required fields are not filled",
                "data": {
                    "name": "",
                    "height": "",
                    "depth": "",
                    "expected_alert_height": expected_alert_text_height,
                    "expected_alert_depth": expected_alert_text_depth
                }
            },
            {
                "name": "Test 3: Only 'Height in units' field is filled",
                "data": {
                    "name": "",
                    "height": "42",
                    "depth": "",
                    "expected_alert_height": expected_alert_text_height,
                    "expected_alert_depth": expected_alert_text_depth
                }
            },
            {
                "name": "Test 4: Only 'Depth (mm)' field is filled",
                "data": {
                    "name": "",
                    "height": "",
                    "depth": "1000",
                    "expected_alert_height": expected_alert_text_height,
                    "expected_alert_depth": expected_alert_text_depth
                }
            }
        ]

        # Выполняем тестовые случаи
        for test_case in test_cases:
            logger.info(test_case["name"])
            self._perform_required_fields_test(
                create_child_frame, rack_maker, test_case["data"]
            )
            logger.info("System prevented creating rack with invalid required fields")

        # 5. Тест: Заполняем все обязательные поля
        logger.info("Test 5: All required fields are filled")

        # Генерируем уникальное имя для финального теста
        final_rack_name = "Test-Rack-Required-Final"

        # Создаем объект данных стойки
        rack_data = RackData(
            name=final_rack_name,
            height="42",
            depth="1000"
        )

        # Заполняем все обязательные поля
        rack_maker.fill_rack_data(rack_data)

        # Проверяем, что ни одно поле не подсвечено цветом ошибки
        create_child_frame.check_field_not_highlighted_error("Имя")
        create_child_frame.check_field_not_highlighted_error("Высота в юнитах")
        create_child_frame.check_field_not_highlighted_error("Глубина (мм)")
        logger.info("No required fields are highlighted with error color - all fields filled correctly")

        # Нажимаем кнопку создания
        create_child_frame.click_add_button()
        create_child_frame.wait_for_timeout(3000)

        # Проверяем, что НЕТ alert-окон для всех обязательных полей
        create_child_frame.alert.check_alert_absence(expected_alert_text_height, 1000)
        create_child_frame.alert.check_alert_absence(expected_alert_text_depth, 1000)
        logger.info("No alert windows for required fields appeared - all fields filled correctly")

        # Проверяем, что ушли со страницы создания
        try:
            create_child_frame.check_toolbar_title('Создать дочерний элемент в')
            logger.warning("Rack creation may not have completed successfully")
        except AssertionError:
            logger.info("Creation page closed - rack successfully created")

        logger.info("Required fields validation test completed successfully")

    def _check_rack_exists(self, browser: Page, rack_name: str) -> bool:
        """Проверяет существование стойки."""
        logger.info(f"Checking existence of rack with name '{rack_name}'")

        # Обновляем навигационную панель
        self.main_page.click_main_navigation_panel_item("Объекты")
        self.main_page.click_main_navigation_panel_item("Объекты")
        self.main_page.wait_for_timeout(1000)
        self.main_page.click_subpanel_item("test-zone")
        self.main_page.wait_for_timeout(3000)

        nav_panel_locator = NavigationPanelLocators.TREEVIEW

        # Проверяем видимость элемента
        element = browser.locator(nav_panel_locator).get_by_text(rack_name).first

        if element.is_visible():
            logger.info(f"Rack with name '{rack_name}' found")
            return True

        logger.info(f"Rack with name '{rack_name}' not found")
        return False

    def _create_rack(self, browser: Page, rack_name: str) -> None:
        """Создает стойку."""
        logger.info(f"Creating rack with name '{rack_name}'")

        # Переходим обратно к созданию новой стойки
        self.main_page.click_main_navigation_panel_item("test-zone")
        self.main_page.wait_for_timeout(2000)

        # Нажимаем кнопку "Создать" на тулбаре
        self.location_page.click_create_button()

        # Создаем фрейм создания дочернего элемента
        create_child_frame = CreateChildElementFrame(browser)

        # Нажимаем на плашку "Класс объекта учета"
        create_child_frame.open_object_class_combobox()

        # Из выпадающего меню выбираем пункт "Стойка"
        create_child_frame.select_object_class("Стойка")

        # Открывается набор плашек для задания параметров стойки
        rack_maker = RackObjectMaker(browser)

        # Создаем объект данных стойки
        rack_data = RackData(
            name=rack_name,
            height="42",
            depth="1000"
        )

        # Заполняем данные стойки
        rack_maker.fill_rack_data(rack_data)

        # Нажимаем кнопку создания
        create_child_frame.click_add_button()
        create_child_frame.wait_for_timeout(2000)
