# -*- coding: utf-8 -*-
# gui/components/_tree_node_building.py
"""Сервис построения узлов дерева и ленивой загрузки (композиция)."""

from __future__ import annotations

from typing import TYPE_CHECKING, Dict, Any

from PySide6.QtCore import Qt
from PySide6.QtWidgets import QTreeWidgetItem

if TYPE_CHECKING:
    from gui.components.topology_tree_widget import TopologyTreeWidget


class TreeNodeBuilder:
    """Создание элементов QTreeWidget и ленивая загрузка дочерних узлов."""

    def __init__(self, host: "TopologyTreeWidget") -> None:
        self._host = host

    def load_root_nodes(self) -> None:
        """Загрузка корневых узлов (сайтов)."""
        try:
            root_nodes = self._host.data_loader('site', None)
            for node_data in root_nodes:
                item = self._create_tree_item(node_data)
                self._host._tree.addTopLevelItem(item)
                if node_data.has_children and not node_data.children_loaded:
                    stub = QTreeWidgetItem(["Загрузка..."])
                    stub.setData(0, Qt.UserRole, {"is_stub": True})
                    item.addChild(stub)
        except Exception as e:
            error_msg = f"Ошибка загрузки корневых узлов: {e}"
            print(error_msg)
            self._host.dataLoadError.emit(error_msg)

    def _create_tree_item(self, node_data) -> QTreeWidgetItem:
        """Создание элемента дерева на основе данных узла."""
        item = QTreeWidgetItem()
        display_attrs = self._host.DISPLAY_ATTRIBUTES.get(node_data.node_type, [])
        col_values = self._get_column_values(
            node_data.display_data, display_attrs, node_data.node_type,
        )
        for i, value in enumerate(col_values):
            if i < self._host._tree.columnCount():
                item.setText(i, str(value))
        item.setData(0, Qt.UserRole, {
            'type': node_data.node_type,
            'id': node_data.node_id,
            'display_data': node_data.display_data,
            'has_children': node_data.has_children,
            'children_loaded': node_data.children_loaded,
            'raw_data': node_data.raw_data,
        })
        item.setChildIndicatorPolicy(
            QTreeWidgetItem.ShowIndicator if node_data.has_children
            else QTreeWidgetItem.DontShowIndicator
        )
        return item

    @staticmethod
    def _get_column_values(
        data: Dict[str, Any], attrs: list[str], node_type: str,
    ) -> list[str]:
        """Значения для колонок (только значения атрибутов, без ключей)."""
        values = []
        if attrs:
            for attr in attrs:
                if attr in data and data[attr]:
                    values.append(str(data[attr]))
                    break
            else:
                values.append("")
        else:
            values.append("")
        if len(attrs) > 1:
            other = [str(data[a]) for a in attrs[1:] if a in data and data[a]]
            sep = " " if node_type == "shelf" else ", "
            values.append(sep.join(other))
        else:
            values.append("")
        return values

    def load_children(self, parent_item: QTreeWidgetItem) -> None:
        """Ленивая загрузка дочерних элементов для узла."""
        parent_data = parent_item.data(0, Qt.UserRole)
        if not parent_data:
            return
        parent_type = parent_data['type']
        parent_id = parent_data['id']
        node_key = f"{parent_type}:{parent_id}"
        if node_key in self._host._loading_nodes:
            return
        self._host._loading_nodes.add(node_key)
        try:
            if parent_item.childCount() == 1:
                child = parent_item.child(0)
                child_data = child.data(0, Qt.UserRole) if child else {}
                if child_data and child_data.get('is_stub'):
                    parent_item.removeChild(child)
            children_data = self._host.data_loader(
                self._get_child_type(parent_type), parent_id,
            )
            for child_data in children_data:
                child_item = self._create_tree_item(child_data)
                parent_item.addChild(child_item)
                if child_data.has_children and not child_data.children_loaded:
                    stub = QTreeWidgetItem(["Загрузка..."])
                    stub.setData(0, Qt.UserRole, {"is_stub": True})
                    child_item.addChild(stub)
            parent_data['children_loaded'] = True
            parent_item.setData(0, Qt.UserRole, parent_data)
            self._host._tree.resizeColumnToContents(0)
        except Exception as e:
            msg = f"Ошибка загрузки дочерних элементов для {parent_type} {parent_id}: {e}"
            print(msg)
            self._host.dataLoadError.emit(msg)
            err_item = QTreeWidgetItem(["Ошибка загрузки", str(e)[:50]])
            err_item.setData(0, Qt.UserRole, {"is_error": True})
            parent_item.addChild(err_item)
        finally:
            self._host._loading_nodes.remove(node_key)

    @staticmethod
    def _get_child_type(parent_type: str) -> str:
        """Тип дочерних элементов на основе типа родителя."""
        hierarchy = {
            'site': 'facility', 'facility': 'zone', 'zone': 'rack',
            'rack': 'shelf', 'shelf': 'cell', 'cell': 'volume',
        }
        return hierarchy.get(parent_type, '')
