"""Модуль создания объекта 'Стойка'."""

from dataclasses import dataclass
from playwright.sync_api import Page
from tools.logger import get_logger
from locators.rack_locators import RackLocators
from components.base_component import BaseComponent

logger = get_logger("RACK_MAKER")


@dataclass
class RackData:
    """Класс для хранения данных стойки."""
    name: str
    height: str = "42"
    depth: str = "1000"
    serial: str = ""
    inventory: str = ""
    comment: str = ""
    cable_entry: str = ""
    state: str = ""
    owner: str = ""
    service_org: str = ""
    project: str = ""


class RackObjectMaker(BaseComponent):
    """Компонент для создания и настройки стойки."""

    def __init__(self, page: Page) -> None:
        """
        Инициализирует компонент создания стойки.

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

    # Действия:

    def fill_rack_data(self, rack_data: RackData) -> None:
        """
        Заполняет данные для создания стойки.

        Args:
            rack_data: Данные стойки
        """
        logger.info(f"Filling rack data: {rack_data.name}")

        self._fill_required_fields(rack_data)
        self._fill_optional_fields(rack_data)
        self._fill_combobox_fields(rack_data)

        logger.info("Rack data filled successfully")

    def _fill_required_fields(self, rack_data: RackData) -> None:
        """Заполняет обязательные поля."""
        if rack_data.name:
            name_field = self.page.locator(RackLocators.RACK_NAME_FIELD).first
            name_field.fill(rack_data.name)
            logger.info(f"Filled 'Name' field: {rack_data.name}")

    def _fill_optional_fields(self, rack_data: RackData) -> None:
        """Заполняет опциональные поля."""
        if rack_data.serial:
            serial_field = self.page.locator(RackLocators.RACK_SERIAL_FIELD).first
            serial_field.fill(rack_data.serial)
            logger.info(f"Filled serial number: {rack_data.serial}")

        if rack_data.inventory:
            inventory_field = self.page.locator(RackLocators.RACK_INVENTORY_FIELD).first
            inventory_field.fill(rack_data.inventory)
            logger.info(f"Filled inventory number: {rack_data.inventory}")

        if rack_data.comment:
            comment_field = self.page.locator(RackLocators.RACK_COMMENT_FIELD).first
            comment_field.fill(rack_data.comment)
            logger.info(f"Added comment: {rack_data.comment}")

    def _fill_combobox_fields(self, rack_data: RackData) -> None:
        """Заполняет combobox поля."""
        if rack_data.height:
            self._fill_combobox_field("Height in units", rack_data.height,
                                     RackLocators.RACK_HEIGHT_FIELD)
            logger.info(f"Selected height: {rack_data.height} units")

        if rack_data.depth:
            self._fill_combobox_field("Depth (mm)", rack_data.depth,
                                     RackLocators.RACK_DEPTH_FIELD)
            logger.info(f"Selected depth: {rack_data.depth} mm")

        if rack_data.cable_entry:
            self._fill_combobox_field("Cable entry", rack_data.cable_entry,
                                     RackLocators.RACK_CABLE_ENTRY_FIELD)
            logger.info(f"Selected cable entry: {rack_data.cable_entry}")

        if rack_data.state:
            self._fill_combobox_field("State", rack_data.state,
                                     RackLocators.RACK_STATE_FIELD)
            logger.info(f"Selected state: {rack_data.state}")

        if rack_data.owner:
            self._fill_combobox_field("Owner", rack_data.owner,
                                     RackLocators.RACK_OWNER_FIELD)
            logger.info(f"Selected owner: {rack_data.owner}")

        if rack_data.service_org:
            self._fill_combobox_field("Service organization", rack_data.service_org,
                                     RackLocators.RACK_SERVICE_ORG_FIELD)
            logger.info(f"Selected service organization: {rack_data.service_org}")

        if rack_data.project:
            self._fill_combobox_field("Project/Title", rack_data.project,
                                     RackLocators.RACK_PROJECT_FIELD)
            logger.info(f"Selected project/title: {rack_data.project}")

    def _fill_combobox_field(self, field_name: str, value: str, field_locator: str) -> None:
        """
        Заполняет combobox поле.

        Args:
            field_name: Название поля
            value: Значение для установки
            field_locator: Локатор поля
        """
        logger.info(f"Filling field '{field_name}' with value '{value}'...")

        # Используем first() для избежания strict mode violation
        field_container = self.page.locator(field_locator).first

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

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

        # Кликаем и вводим значение
        field_container.click(force=True)
        self.wait_for_timeout(1000)

        # Вводим значение
        self.page.keyboard.type(value)
        self.wait_for_timeout(500)
        self.page.keyboard.press("Enter")

        logger.info(f"Field '{field_name}' filled successfully")

    def _get_field_locator(self, field_name: str) -> str:
        """
        Возвращает локатор поля по его названию.

        Args:
            field_name: Название поля

        Returns:
            str: Локатор поля
        """
        field_map = {
            "Имя": RackLocators.RACK_NAME_FIELD,
            "Высота в юнитах": RackLocators.RACK_HEIGHT_FIELD,
            "Глубина (мм)": RackLocators.RACK_DEPTH_FIELD
        }

        if field_name not in field_map:
            raise ValueError(f"Field '{field_name}' is not supported")

        return field_map[field_name]

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

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

    # Проверки:

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

        Raises:
            AssertionError: Если какое-либо поле не найдено
        """
        logger.info("Checking rack fields presence...")

        # Основные обязательные поля
        required_fields = [
            (RackLocators.RACK_NAME_FIELD, "Name"),
            (RackLocators.RACK_HEIGHT_FIELD, "Height in units"),
            (RackLocators.RACK_DEPTH_FIELD, "Depth (mm)")
        ]

        # Дополнительные поля
        optional_fields = [
            (RackLocators.RACK_SERIAL_FIELD, "Serial number"),
            (RackLocators.RACK_INVENTORY_FIELD, "Inventory number"),
            (RackLocators.RACK_COMMENT_FIELD, "Comment"),
            (RackLocators.RACK_CABLE_ENTRY_FIELD, "Cable entry"),
            (RackLocators.RACK_STATE_FIELD, "State"),
            (RackLocators.RACK_OWNER_FIELD, "Owner"),
            (RackLocators.RACK_SERVICE_ORG_FIELD, "Service organization"),
            (RackLocators.RACK_PROJECT_FIELD, "Project/Title")
        ]

        # Проверяем обязательные поля
        for field_locator, field_name in required_fields:
            field = self.page.locator(field_locator).first
            self.check_visibility(field, f"Required field '{field_name}' not found")
            logger.info(f"Required field '{field_name}' found")

        # Проверяем дополнительные поля
        for field_locator, field_name in optional_fields:
            field = self.page.locator(field_locator).first
            if field.count() > 0 and field.is_visible():
                logger.info(f"Optional field '{field_name}' found")
            else:
                logger.info(f"Optional field '{field_name}' not found or not visible")

        logger.info("All main rack fields are present")
