# -*- coding: utf-8 -*-
# gui/components/photo_view_widget.py
"""Виджет для отображения фотографий видов"""

from pathlib import Path

from PySide6.QtWidgets import QLabel, QSizePolicy
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QPixmap

from gui.containers import VContainer, SContainer
from gui.styles import APP_STYLES


class PhotoViewWidget(SContainer):
    """Виджет для отображения фотографий видов"""

    error_occurred = Signal(str)

    def __init__(self, content_fit: bool = True):
        super().__init__(width_percent=None, height_percent=None)
        self._content_fit = content_fit
        self._current_zoom = 1.0
        self._current_view = None
        self._images = {}  # {имя_вида: QPixmap}
        self._base_pixmap = None
        self.setup_ui()

    def setup_ui(self):
        main_container = VContainer(
            content_fit=self._content_fit,
            parent=self,
        )

        self._image_label = QLabel()
        self._image_label.setAlignment(Qt.AlignCenter)
        self._image_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._image_label.setMinimumSize(1, 1)

        # Важно: scaledContents=False, иначе некорректно комбинируется с зумом/KeepAspectRatio
        self._image_label.setScaledContents(False)
        
        # Устанавливаем фон как у главного окна
        self.setStyleSheet(APP_STYLES.get("VIEW_WIDGET_BACKGROUND", ""))
        self._image_label.setStyleSheet(APP_STYLES.get("VIEW_IMAGE_BACKGROUND", ""))

        main_container.add_widget_with_stretch(self._image_label, 1)
    def load_images(self, images_dict):
        """Загрузка изображений"""
        self.clear_images()

        if not images_dict:
            self.show_error("Изображения не указаны")
            return

        loaded_count = 0
        for view_name, image_path in images_dict.items():
            p = Path(image_path)
            if not p.exists():
                continue

            pixmap = QPixmap(str(p))
            if pixmap.isNull():
                continue

            self._images[view_name] = pixmap
            loaded_count += 1

        if loaded_count == 0:
            self.show_error("Не удалось загрузить ни одного изображения")
            return

        first_view = list(self._images.keys())[0]
        self.show_view(first_view)

    def clear_images(self):
        """Очистка изображений"""
        self._images.clear()
        self._current_view = None
        self._base_pixmap = None
        self._image_label.clear()
        self._current_zoom = 1.0

    def show_view(self, view_name):
        """Показать изображение вида"""
        if view_name not in self._images:
            return

        self._current_view = view_name
        self._base_pixmap = self._images[view_name]
        self.update_display()

    def switch_view_cycle(self, preferred_order):
        """Циклическое переключение вида с предпочтительным порядком"""
        if not self._images or not self._current_view:
            return

        available_views = [v for v in preferred_order if v in self._images]
        if not available_views:
            return

        if self._current_view in available_views:
            current_index = available_views.index(self._current_view)
            next_index = (current_index + 1) % len(available_views)
        else:
            next_index = 0

        self.show_view(available_views[next_index])

    def switch_to_isometric_or_next(self):
        """Переключение на изометрический вид или следующий в цикле"""
        if not self._images:
            return

        if 'isometric' in self._images and self._current_view != 'isometric':
            self.show_view('isometric')
            return

        available_views = list(self._images.keys())
        if not available_views:
            return

        if self._current_view in available_views:
            i = available_views.index(self._current_view)
            self.show_view(available_views[(i + 1) % len(available_views)])
        else:
            self.show_view(available_views[0])

    def update_display(self):
        """Обновление отображения изображения с учетом зума"""
        if self._base_pixmap is None or self._base_pixmap.isNull():
            return

        # Базовый размер — размер label, дальше умножаем на zoom
        target = self._image_label.size()
        if target.width() <= 1 or target.height() <= 1:
            return

        w = max(1, int(target.width() * self._current_zoom))
        h = max(1, int(target.height() * self._current_zoom))

        scaled = self._base_pixmap.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self._image_label.setPixmap(scaled)

    def zoom_in(self):
        self._current_zoom = min(self._current_zoom * 1.2, 5.0)
        self.update_display()

    def zoom_out(self):
        self._current_zoom = max(self._current_zoom / 1.2, 0.2)
        self.update_display()

    def reset_zoom(self):
        self._current_zoom = 1.0
        self.update_display()

    def show_error(self, message):
        self.clear_images()
        self.error_occurred.emit(message)

    def wheelEvent(self, event):
        if self._images:
            delta = event.angleDelta().y()
            if delta > 0:
                self.zoom_in()
            else:
                self.zoom_out()
        event.accept()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_display()

    def set_enabled(self, enabled: bool) -> None:
        self.setEnabled(enabled)

    def set_min_width(self, width: int) -> None:
        self.setMinimumWidth(width)

    def set_min_height(self, height: int) -> None:
        self.setMinimumHeight(height)

    def set_max_width(self, width: int) -> None:
        self.setMaximumWidth(width)

    def set_max_height(self, height: int) -> None:
        self.setMaximumHeight(height)

    def set_fixed_size(self, width: int, height: int) -> None:
        self.setMinimumSize(width, height)
        self.setMaximumSize(width, height)

    def set_tooltip(self, text: str) -> None:
        self.setToolTip(text)

    def set_size_policy(self, horizontal, vertical) -> None:
        self.setSizePolicy(horizontal, vertical)






# ---------------------------------------------------------------------------
# Module workflow notes
# ---------------------------------------------------------------------------
#
# 1) Назначение модуля:
#    Виджет для отображения фотографий видов детали с поддержкой
#    зума (колесо мыши), циклического переключения видов и
#    масштабирования с сохранением пропорций (KeepAspectRatio).
#
# 2) Зависимости модуля:
#    Импорты: Path (pathlib),
#             QLabel, QSizePolicy (PySide6.QtWidgets),
#             Qt, Signal (PySide6.QtCore),
#             QPixmap (PySide6.QtGui),
#             VContainer, SContainer (gui.containers),
#             APP_STYLES (gui.styles)
#    Хост-класс / базовый класс: SContainer
#    Внешние библиотеки: PySide6 (обязательна)
#
# 3) Экспорт:
#    Класс PhotoViewWidget — виджет фотогалереи.
#    Сигнал: error_occurred(str).
#    Методы: load_images(dict), clear_images(), show_view(str),
#            switch_view_cycle(list), switch_to_isometric_or_next(),
#            update_display(), zoom_in(), zoom_out(), reset_zoom(),
#            show_error().
#
# 4) Состояние (поля):
#    _content_fit: bool        — режим подгонки
#    _current_zoom: float      — текущий множитель зума (1.0 = 100%)
#    _current_view: str|None   — имя текущего вида
#    _images: dict             — {имя_вида: QPixmap}
#    _base_pixmap: QPixmap|None— исходный pixmap текущего вида
#    _image_label: QLabel      — виджет отображения изображения
#
# 5) Последовательность действий и вызовов:
#    __init__(content_fit)
#      -> super().__init__(...)
#      -> setup_ui() — VContainer + QLabel с Expanding + stylesheet
#    load_images(images_dict)
#      -> clear_images() -> для каждого пути: Path.exists() -> QPixmap
#      -> show_view(first_view)
#    show_view(view_name)
#      -> _base_pixmap = _images[view_name] -> update_display()
#    update_display()
#      -> размер label * _current_zoom -> scaled(KeepAspectRatio, SmoothTransformation)
#      -> _image_label.setPixmap(scaled)
#    wheelEvent(event)
#      -> delta > 0: zoom_in() | delta < 0: zoom_out()
#    resizeEvent(event)
#      -> update_display() — адаптация к новому размеру
#
# 6) Побочные эффекты:
#    - Загружает файлы изображений с диска.
#    - Устанавливает stylesheet через APP_STYLES.
#    - Испускает error_occurred при ошибках.
#
# 7) Границы ответственности:
#    Модуль НЕ управляет источником изображений (каталогом).
#    НЕ редактирует файлы. НЕ подключается к theme_bus.
#
# 8) Обработка ошибок:
#    load_images() проверяет Path.exists() и QPixmap.isNull().
#    show_error() очищает изображения и испускает error_occurred.
#
# 9) Инварианты и контракты:
#    - _current_zoom ∈ [0.2, 5.0].
#    - scaledContents = False — масштабирование управляется вручную.
#    - Если _base_pixmap is None — update_display() не делает ничего.
#
# 10) Правило сопровождения:
#     Для добавления поддержки drag-and-drop или аннотаций — расширять
#     подкласс, не модифицировать этот файл. Зум-границы (0.2–5.0) —
#     константы в zoom_in/zoom_out.
