import sys
import os
import json
import ctypes
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QFileDialog, QLabel, QListWidget,
    QListWidgetItem, QHBoxLayout, QVBoxLayout, QPushButton, QMenu, QAction,
    QMessageBox, QScrollArea, QSizePolicy, QSplitter, QTreeView, QFileSystemModel
)
from PyQt5.QtGui import QPixmap, QIcon, QPalette, QMouseEvent, QWheelEvent, QColor
from PyQt5.QtCore import Qt, QSize, QSettings, QDir, QPoint, QStandardPaths, pyqtSignal
from PIL import Image

try:
    import winreg  # Только на Windows
except ImportError:
    winreg = None  # Если не на Windows, модуль недоступен


# Путь к папке кеша
CACHE_DIR = os.path.join(os.path.expanduser("~"), ".image_viewer_cache")
FAVORITES_FILE = os.path.join(CACHE_DIR, "favorites.json")

SUPPORTED_FORMATS = ('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff')


def ensure_cache():
    """
    Создает папку для кеша, если она не существует.
    """
    if not os.path.exists(CACHE_DIR):
        os.makedirs(CACHE_DIR)


def is_windows_dark_mode():
    """
    Проверяет, использует ли Windows темную тему для приложений.
    Возвращает True, если темная тема включена, иначе False.
    """
    if winreg is None:
        return False  # По умолчанию светлая тема, если невозможно определить

    try:
        registry = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
        key_path = r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"
        key = winreg.OpenKey(registry, key_path)
        value, regtype = winreg.QueryValueEx(key, "AppsUseLightTheme")
        winreg.CloseKey(key)
        return value == 0  # 0 означает темная тема, 1 - светлая
    except FileNotFoundError:
        return False  # Если ключ не найден, предположить светлую тему
    except Exception as e:
        print(f"Ошибка при определении темы Windows: {e}")
        return False


class ImageLabel(QLabel):
    """
    QLabel для отображения изображения с возможностью масштабирования и панорамирования.
    """
    double_clicked = pyqtSignal()  # Сигнал для двойного щелчка мыши

    def __init__(self, parent=None, parent_scroll=None):
        super().__init__(parent)
        self.setBackgroundRole(QPalette.Window)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)  # Позволяет QLabel расширяться
        self.setScaledContents(False)  # Отключаем автоматическое масштабирование
        self.scale_factor = 1.0
        self.original_pixmap = None
        self.min_scale_factor = 1.0  # Минимальный коэффициент масштабирования

        # Для панорамирования
        self.setMouseTracking(True)
        self._drag_pos = None
        self.parent_scroll = parent_scroll  # Ссылка на QScrollArea

    def set_pixmap(self, pixmap):
        """
        Устанавливает изображение и вычисляет минимальный масштаб.
        """
        self.original_pixmap = pixmap
        self.calculate_min_scale()
        self.scale_factor = self.min_scale_factor
        self.update_pixmap()

    def calculate_min_scale(self):
        """
        Вычисляет минимальный коэффициент масштабирования, чтобы изображение полностью помещалось в область просмотра.
        """
        if self.original_pixmap and self.parent_scroll:
            viewport_size = self.parent_scroll.viewport().size()
            if viewport_size.width() == 0 or viewport_size.height() == 0:
                # Избегаем деления на ноль
                self.min_scale_factor = 1.0
                return
            pixmap_size = self.original_pixmap.size()

            scale_w = viewport_size.width() / pixmap_size.width()
            scale_h = viewport_size.height() / pixmap_size.height()

            self.min_scale_factor = min(scale_w, scale_h, 1.0)  # Не увеличивать изображение при малых размерах

    def update_pixmap(self):
        """
        Обновление отображаемого изображения с учетом текущего коэффициента масштабирования.
        """
        if self.original_pixmap:
            new_size = self.scale_factor * self.original_pixmap.size()
            scaled_pixmap = self.original_pixmap.scaled(
                new_size, Qt.KeepAspectRatio, Qt.SmoothTransformation
            )
            self.setPixmap(scaled_pixmap)
            self.adjustSize()  # Корректирует размер QLabel под новое изображение

    def wheelEvent(self, event: QWheelEvent):
        """
        Обработка события прокрутки колесика мыши для масштабирования изображения.
        Масштабирование происходит относительно позиции курсора.
        """
        if event.angleDelta().y() > 0:
            self.zoom_in(event.pos())
        else:
            self.zoom_out(event.pos())

    def zoom_in(self, cursor_pos=None):
        """
        Увеличение изображения.
        """
        self.scale_image(1.1, cursor_pos)

    def zoom_out(self, cursor_pos=None):
        """
        Уменьшение изображения.
        """
        self.scale_image(0.9, cursor_pos)

    def scale_image(self, factor, cursor_pos=None):
        """
        Масштабирование изображения на заданный коэффициент с сохранением позиции курсора.
        """
        if self.original_pixmap is None:
            return

        # Ограничение коэффициента масштабирования
        new_scale = self.scale_factor * factor
        if new_scale < self.min_scale_factor:
            new_scale = self.min_scale_factor
        elif new_scale > 10:
            new_scale = 10
        scale_change = new_scale / self.scale_factor  # Корректировка фактора масштабирования
        self.scale_factor = new_scale

        # Сохранение координат курсора до масштабирования
        if cursor_pos and self.parent_scroll:
            # Координаты курсора относительно QLabel
            cursor_x = cursor_pos.x()
            cursor_y = cursor_pos.y()

            # Процент позиции курсора относительно размера перед масштабированием
            if self.original_pixmap.width() != 0 and self.original_pixmap.height() != 0:
                ratio_x = cursor_x / self.original_pixmap.width()
                ratio_y = cursor_y / self.original_pixmap.height()
            else:
                ratio_x = 0.5
                ratio_y = 0.5

        # Обновление изображения
        self.update_pixmap()

        # Настройка прокрутки
        if cursor_pos and self.parent_scroll and self.original_pixmap.width() != 0 and self.original_pixmap.height() != 0:
            h_scroll = self.parent_scroll.horizontalScrollBar()
            v_scroll = self.parent_scroll.verticalScrollBar()

            # Новые размеры изображения
            new_pixmap_width = self.original_pixmap.width() * self.scale_factor
            new_pixmap_height = self.original_pixmap.height() * self.scale_factor

            # Новые позиции прокрутки
            new_h = int(new_pixmap_width * ratio_x - self.parent_scroll.viewport().width() / 2)
            new_v = int(new_pixmap_height * ratio_y - self.parent_scroll.viewport().height() / 2)

            # Ограничение значений прокрутки
            new_h = max(new_h, 0)
            new_v = max(new_v, 0)

            # Установка новых значений прокрутки
            h_scroll.setValue(new_h)
            v_scroll.setValue(new_v)
        else:
            # Если позиция курсора неизвестна, не центрировать
            pass  # Делаем ничего, чтобы изображение оставалось в том месте, где было

    def mousePressEvent(self, event: QMouseEvent):
        """
        Обработка нажатия кнопок мыши для панорамирования.
        """
        if event.button() == Qt.LeftButton:
            self._drag_pos = event.globalPos()
            self.setCursor(Qt.ClosedHandCursor)
            event.accept()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event: QMouseEvent):
        """
        Обработка перемещения мыши для панорамирования.
        """
        if self._drag_pos is not None and event.buttons() & Qt.LeftButton:
            delta = event.globalPos() - self._drag_pos
            self._drag_pos = event.globalPos()
            if self.parent_scroll:
                h_scroll = self.parent_scroll.horizontalScrollBar()
                v_scroll = self.parent_scroll.verticalScrollBar()
                h_scroll.setValue(h_scroll.value() - delta.x())
                v_scroll.setValue(v_scroll.value() - delta.y())
            event.accept()
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event: QMouseEvent):
        """
        Обработка отпускания кнопок мыши после панорамирования.
        """
        if event.button() == Qt.LeftButton:
            self._drag_pos = None
            self.setCursor(Qt.ArrowCursor)
            event.accept()
        super().mouseReleaseEvent(event)

    def resizeEvent(self, event):
        """
        Обработка изменения размера QLabel для пересчета минимального масштаба.
        """
        super().resizeEvent(event)
        self.calculate_min_scale()
        if self.scale_factor < self.min_scale_factor:
            self.scale_factor = self.min_scale_factor
            self.update_pixmap()

    def mouseDoubleClickEvent(self, event: QMouseEvent):
        """
        Обработка двойного щелчка мыши для переключения полноэкранного режима.
        """
        if event.button() == Qt.LeftButton:
            self.double_clicked.emit()
        super().mouseDoubleClickEvent(event)


class ImageViewer(QMainWindow):
    """
    Основное окно приложения ImageViewer.
    """
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Просмотровщик Изображений")
        self.resize(1200, 800)
        self.fullscreen = False  # Флаг полноэкранного режима

        ensure_cache()
        self.favorites = self.load_favorites()
        self.clipboard_path = None
        self.copied = False

        # Настройка QSettings для сохранения настроек
        self.settings = QSettings("MyCompany", "ImageViewer")

        # Основной виджет и компоновка
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout()
        self.central_widget.setLayout(self.main_layout)
        self.main_layout.setContentsMargins(5, 5, 5, 5)  # Уменьшаем отступы

        # Панель инструментов
        self.toolbar_widget = QWidget()  # Создаем виджет для панели инструментов
        self.toolbar = QHBoxLayout()
        self.toolbar.setContentsMargins(0, 0, 0, 0)  # Убираем отступы внутри панели
        self.toolbar_widget.setLayout(self.toolbar)
        self.toolbar_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)  # Фиксированная высота
        self.toolbar_widget.setFixedHeight(40)  # Установите желаемую фиксированную высоту панели инструментов
        self.main_layout.addWidget(self.toolbar_widget)

        # Добавление кнопок в панель инструментов
        self.open_folder_btn = QPushButton("Открыть папку")
        self.open_folder_btn.clicked.connect(self.open_folder)
        self.toolbar.addWidget(self.open_folder_btn)

        self.open_file_btn = QPushButton("Открыть файл")
        self.open_file_btn.clicked.connect(self.open_file)
        self.toolbar.addWidget(self.open_file_btn)

        self.edit_btn = QPushButton("Изменить (Paint)")
        self.edit_btn.clicked.connect(self.edit_image)
        self.toolbar.addWidget(self.edit_btn)

        self.delete_btn = QPushButton("Удалить")
        self.delete_btn.clicked.connect(self.delete_image)
        self.toolbar.addWidget(self.delete_btn)

        self.fullscreen_btn = QPushButton("На весь экран")
        self.fullscreen_btn.clicked.connect(self.toggle_fullscreen)
        self.toolbar.addWidget(self.fullscreen_btn)

        self.png_info_btn = QPushButton("PNG info")
        self.png_info_btn.clicked.connect(self.png_info)
        self.toolbar.addWidget(self.png_info_btn)

        self.favorites_btn = QPushButton("Избранное")
        self.favorites_btn.clicked.connect(self.show_favorites)
        self.toolbar.addWidget(self.favorites_btn)

        self.save_size_btn = QPushButton("Сохранить размер")
        self.save_size_btn.clicked.connect(self.save_window_size)
        self.toolbar.addWidget(self.save_size_btn)

        # Добавление кнопки для доступа к Рабочему столу
        self.desktop_btn = QPushButton("Рабочий стол")
        self.desktop_btn.clicked.connect(self.open_desktop)
        self.toolbar.addWidget(self.desktop_btn)

        # Добавление растяжения, чтобы кнопки были слева при широкой панели
        self.toolbar.addStretch()

        # Основная область с разделителями и списками и изображением
        self.splitter_main = QSplitter(Qt.Horizontal)
        self.main_layout.addWidget(self.splitter_main)

        # Левая панель: Дерево папок
        self.file_model = QFileSystemModel()
        self.file_model.setRootPath("")  # Показать все корневые диски
        self.file_model.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot | QDir.Drives)

        self.navigation_tree = QTreeView()
        self.navigation_tree.setModel(self.file_model)
        self.navigation_tree.setRootIndex(self.file_model.index(""))
        self.navigation_tree.setColumnWidth(0, 250)
        self.navigation_tree.hideColumn(1)  # Размер
        self.navigation_tree.hideColumn(2)  # Тип
        self.navigation_tree.hideColumn(3)  # Дата
        self.navigation_tree.clicked.connect(self.navigate_to_directory)
        self.splitter_main.addWidget(self.navigation_tree)

        # Средняя панель: Превью изображений
        self.splitter_images = QSplitter(Qt.Vertical)
        self.splitter_main.addWidget(self.splitter_images)

        self.image_list = QListWidget()
        self.image_list.setViewMode(QListWidget.IconMode)
        self.image_list.setResizeMode(QListWidget.Adjust)
        self.image_list.setMovement(QListWidget.Static)
        self.image_list.setWordWrap(True)
        self.image_list.setWrapping(True)
        self.image_list.setSpacing(10)
        self.image_list.setIconSize(QSize(150, 150))  # Увеличенные иконки для лучшего отображения
        self.image_list.setSelectionMode(QListWidget.SingleSelection)
        self.image_list.itemClicked.connect(self.display_image)
        self.splitter_images.addWidget(self.image_list)

        # Правая панель: Область просмотра изображения
        self.image_area = QScrollArea()
        self.image_area.setAlignment(Qt.AlignCenter)  # Центрирование содержимого
        self.image_label = ImageLabel(parent_scroll=self.image_area)  # Передача ссылки на QScrollArea
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_area.setWidget(self.image_label)
        self.image_area.setWidgetResizable(True)  # Позволяет QScrollArea управлять размером виджета
        self.splitter_main.addWidget(self.image_area)

        # Устанавливаем начальные пропорции разделителей, если они сохранены
        self.load_splitter_proportions()

        # Загрузка окна
        self.load_window_state()

        # Применение темы
        self.apply_theme()

        # Поддержка drag and drop
        self.setAcceptDrops(True)

        # Подключение сигнала двойного щелчка
        self.image_label.double_clicked.connect(self.toggle_fullscreen)

        # Открытие последней директории, если она сохранена
        last_dir = self.settings.value("last_directory")
        if last_dir and os.path.isdir(last_dir):
            self.current_folder = last_dir
            self.load_images(last_dir)
            self.select_first_image()

    def load_favorites(self):
        """
        Загрузка списка избранных изображений из файла.
        """
        if os.path.exists(FAVORITES_FILE):
            try:
                with open(FAVORITES_FILE, 'r', encoding='utf-8') as f:
                    return set(json.load(f))
            except Exception as e:
                print(f"Ошибка загрузки избранного: {e}")
                return set()
        return set()

    def save_favorites(self):
        """
        Сохранение списка избранных изображений в файл.
        """
        try:
            with open(FAVORITES_FILE, 'w', encoding='utf-8') as f:
                json.dump(list(self.favorites), f, ensure_ascii=False, indent=4)
        except Exception as e:
            print(f"Ошибка сохранения избранного: {e}")

    def open_folder(self):
        """
        Открытие диалога выбора папки и загрузка изображений из выбранной папки.
        """
        folder = QFileDialog.getExistingDirectory(self, "Выбрать папку", "")
        if folder:
            self.current_folder = folder
            self.settings.setValue("last_directory", folder)  # Сохранение последней директории
            self.load_images(folder)
            self.select_first_image()

    def open_file(self):
        """
        Открытие диалога выбора файла и загрузка соответствующей папки.
        """
        file, _ = QFileDialog.getOpenFileName(
            self, "Выбрать файл", "", "Images (*.png *.jpg *.jpeg *.bmp *.gif *.tiff)"
        )
        if file:
            folder = os.path.dirname(file)
            self.current_folder = folder
            self.settings.setValue("last_directory", folder)  # Сохранение последней директории
            self.load_images(folder)
            self.select_image(file)

    def load_images(self, folder):
        """
        Загрузка изображений из указанной папки и отображение их в виде превью.
        """
        try:
            self.image_list.clear()
            for filename in os.listdir(folder):
                if filename.lower().endswith(SUPPORTED_FORMATS):
                    filepath = os.path.join(folder, filename)
                    thumbnail = self.get_thumbnail(filepath)
                    if thumbnail:
                        item = QListWidgetItem()
                        item.setIcon(QIcon(thumbnail))
                        item.setData(Qt.UserRole, filepath)
                        self.image_list.addItem(item)
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось загрузить изображения: {e}")

    def get_thumbnail(self, filepath):
        """
        Создание или загрузка превью изображения из кеша.
        """
        try:
            ensure_cache()
            thumb_filename = self.sanitize_filename(filepath) + ".png"
            thumb_path = os.path.join(CACHE_DIR, thumb_filename)
            if not os.path.exists(thumb_path):
                img = Image.open(filepath)
                img.thumbnail((150, 150))  # Размер превью соответствует установленному IconSize
                img.save(thumb_path, "PNG")
            return thumb_path
        except Exception as e:
            print(f"Ошибка создания превью для {filepath}: {e}")
            return None

    def sanitize_filename(self, filepath):
        """
        Преобразование пути к файлу в допустимое имя файла для превью.
        """
        return filepath.replace(os.sep, "_").replace(":", "_").replace("\\", "_").replace("/", "_").replace(" ", "_")

    def display_image(self, item):
        """
        Отображение выбранного изображения в основном окне с возможностью масштабирования и панорамирования.
        """
        try:
            filepath = item.data(Qt.UserRole)
            pixmap = QPixmap(filepath)
            if pixmap.isNull():
                QMessageBox.warning(self, "Ошибка", f"Не удалось загрузить изображение: {filepath}")
                return
            self.image_label.set_pixmap(pixmap)
            self.current_image = filepath
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось отобразить изображение: {e}")

    def select_image(self, filepath):
        """
        Выбор изображения в списке по его пути и отображение.
        """
        try:
            for index in range(self.image_list.count()):
                item = self.image_list.item(index)
                if item.data(Qt.UserRole) == filepath:
                    self.image_list.setCurrentItem(item)
                    self.display_image(item)
                    break
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось выбрать изображение: {e}")

    def select_first_image(self):
        """
        Выбор и отображение первого изображения в списке.
        """
        try:
            if self.image_list.count() > 0:
                self.image_list.setCurrentRow(0)
                item = self.image_list.item(0)
                self.display_image(item)
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось выбрать первое изображение: {e}")

    def edit_image(self):
        """
        Открытие выбранного изображения в Paint для редактирования.
        """
        if self.current_image:
            try:
                if sys.platform.startswith('win'):
                    os.startfile(self.current_image, 'edit')
                else:
                    QMessageBox.warning(self, "Ошибка", "Функция редактирования доступна только на Windows.")
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось открыть изображение для редактирования: {e}")

    def delete_image(self):
        """
        Удаление выбранного изображения с подтверждением.
        """
        if self.current_image:
            reply = QMessageBox.question(
                self, 'Удаление',
                f"Вы действительно хотите удалить {os.path.basename(self.current_image)}?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                try:
                    os.remove(self.current_image)
                    self.load_images(self.current_folder)
                    self.image_label.clear()
                    self.current_image = None
                except Exception as e:
                    QMessageBox.warning(self, "Ошибка", f"Не удалось удалить файл: {e}")

    def toggle_fullscreen(self):
        """
        Переключение полноэкранного режима.
        """
        if self.fullscreen:
            self.showNormal()
            self.fullscreen = False
            self.toolbar_widget.setVisible(True)  # Показать панель инструментов
        else:
            self.showFullScreen()
            self.fullscreen = True
            self.toolbar_widget.setVisible(False)  # Скрыть панель инструментов для большей области просмотра

    def png_info(self):
        """
        Отображение информации о PNG-изображении.
        """
        if self.current_image and self.current_image.lower().endswith('.png'):
            try:
                img = Image.open(self.current_image)
                info = img.info
                msg = "\n".join([f"{k}: {v}" for k, v in info.items()])
                QMessageBox.information(self, "PNG Info", msg)
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось получить информацию о PNG: {e}")
        else:
            QMessageBox.information(self, "Информация", "Текущее изображение не является PNG.")

    def show_favorites(self):
        """
        Отображение списка избранных изображений.
        """
        try:
            favorite_images = list(self.favorites)
            if not favorite_images:
                QMessageBox.information(self, "Избранное", "Список избранных изображений пуст.")
                return
            self.image_list.clear()
            for filepath in favorite_images:
                if os.path.exists(filepath):
                    thumbnail = self.get_thumbnail(filepath)
                    if thumbnail:
                        item = QListWidgetItem()
                        item.setIcon(QIcon(thumbnail))
                        item.setData(Qt.UserRole, filepath)
                        self.image_list.addItem(item)
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось отобразить избранные изображения: {e}")

    def save_window_size(self):
        """
        Сохранение текущего размера и положения окна.
        """
        try:
            self.settings.setValue("size", self.size())
            self.settings.setValue("pos", self.pos())
            QMessageBox.information(self, "Сохранено", "Размер и положение окна сохранены.")
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось сохранить размеры окна: {e}")

    def load_window_state(self):
        """
        Загрузка сохраненного размера и положения окна, а также состояний разделителей.
        """
        try:
            size = self.settings.value("size")
            pos = self.settings.value("pos")
            if size:
                self.resize(size)
            if pos:
                self.move(pos)

            # Загрузка пропорций разделителей
            self.load_splitter_proportions()
        except Exception as e:
            print(f"Ошибка загрузки состояния окна: {e}")

    def contextMenuEvent(self, event):
        """
        Создание и отображение контекстного меню при правом клике на изображение.
        """
        if not self.current_image:
            return  # Не показывать контекстное меню, если нет выбранного изображения

        context_menu = QMenu(self)

        if self.current_image in self.favorites:
            remove_fav_action = QAction("Удалить из избранного", self)
            remove_fav_action.triggered.connect(self.remove_from_favorites)
            context_menu.addAction(remove_fav_action)
        else:
            add_fav_action = QAction("Добавить в избранное", self)
            add_fav_action.triggered.connect(self.add_to_favorites)
            context_menu.addAction(add_fav_action)

        copy_action = QAction("Копировать", self)
        copy_action.triggered.connect(self.copy_file)
        context_menu.addAction(copy_action)

        paste_action = QAction("Вставить", self)
        paste_action.triggered.connect(self.paste_file)
        context_menu.addAction(paste_action)

        cut_action = QAction("Вырезать", self)
        cut_action.triggered.connect(self.cut_file)
        context_menu.addAction(cut_action)

        set_wallpaper_action = QAction("Сделать изображением рабочего стола", self)
        set_wallpaper_action.triggered.connect(self.set_as_wallpaper)
        context_menu.addAction(set_wallpaper_action)

        properties_action = QAction("Свойства", self)
        properties_action.triggered.connect(self.show_properties)
        context_menu.addAction(properties_action)

        context_menu.exec_(event.globalPos())

    def add_to_favorites(self):
        """
        Добавление текущего изображения в избранное.
        """
        if self.current_image:
            try:
                self.favorites.add(self.current_image)
                self.save_favorites()
                QMessageBox.information(
                    self, "Избранное",
                    f"Добавлено в избранное: {os.path.basename(self.current_image)}"
                )
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось добавить в избранное: {e}")

    def remove_from_favorites(self):
        """
        Удаление текущего изображения из избранного.
        """
        if self.current_image and self.current_image in self.favorites:
            try:
                self.favorites.remove(self.current_image)
                self.save_favorites()
                QMessageBox.information(
                    self, "Избранное",
                    f"Удалено из избранного: {os.path.basename(self.current_image)}"
                )
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось удалить из избранного: {e}")

    def copy_file(self):
        """
        Копирование текущего изображения в буфер обмена.
        """
        if self.current_image:
            try:
                self.copied = True
                self.clipboard_path = self.current_image
                QMessageBox.information(
                    self, "Копирование",
                    f"Скопировано: {os.path.basename(self.current_image)}"
                )
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось скопировать файл: {e}")

    def paste_file(self):
        """
        Вставка изображения из буфера обмена в текущую папку.
        """
        if self.clipboard_path and self.current_folder:
            try:
                base, name = os.path.split(self.clipboard_path)
                dest = os.path.join(self.current_folder, name)
                if os.path.exists(dest):
                    QMessageBox.warning(
                        self, "Копирование",
                        "Файл уже существует в папке назначения."
                    )
                    return
                if self.copied:
                    # Копирование
                    with open(self.clipboard_path, 'rb') as fr:
                        with open(dest, 'wb') as fw:
                            fw.write(fr.read())
                    self.load_images(self.current_folder)
                    QMessageBox.information(
                        self, "Копирование",
                        f"Вставлено: {dest}"
                    )
                else:
                    # Вырезание
                    if os.path.exists(self.clipboard_path):
                        with open(self.clipboard_path, 'rb') as fr:
                            with open(dest, 'wb') as fw:
                                fw.write(fr.read())
                        os.remove(self.clipboard_path)
                        self.load_images(self.current_folder)
                        QMessageBox.information(
                            self, "Вырезание",
                            f"Вставлено: {dest}"
                        )
            except Exception as e:
                QMessageBox.warning(
                    self, "Копирование/Вырезание",
                    f"Не удалось вставить файл: {e}"
                )
        else:
            QMessageBox.information(
                self, "Вставка", "Буфер обмена пуст или не выбрана папка назначения."
            )

    def cut_file(self):
        """
        Вырезание текущего изображения.
        """
        if self.current_image:
            try:
                self.copied = False
                self.clipboard_path = self.current_image
                QMessageBox.information(
                    self, "Вырезание",
                    f"Вырезано: {os.path.basename(self.current_image)}"
                )
            except Exception as e:
                QMessageBox.warning(self, "Ошибка", f"Не удалось вырезать файл: {e}")

    def set_as_wallpaper(self):
        """
        Установка текущего изображения как фон рабочего стола (только для Windows).
        """
        if self.current_image:
            try:
                if sys.platform.startswith('win'):
                    SPI_SETDESKWALLPAPER = 20
                    abs_path = os.path.abspath(self.current_image)
                    ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, abs_path, 3)
                    QMessageBox.information(
                        self, "Рабочий стол",
                        "Фон рабочего стола установлен."
                    )
                else:
                    QMessageBox.warning(self, "Ошибка", "Функция доступна только на Windows.")
            except Exception as e:
                QMessageBox.warning(
                    self, "Ошибка",
                    f"Не удалось установить фон: {e}"
                )

    def show_properties(self):
        """
        Отображение свойств текущего изображения.
        """
        if self.current_image:
            try:
                stat = os.stat(self.current_image)
                info = (
                    f"Путь: {self.current_image}\n"
                    f"Размер: {stat.st_size} байт\n"
                    f"Последнее изменение: {self.format_time(stat.st_mtime)}"
                )
                QMessageBox.information(self, "Свойства", info)
            except Exception as e:
                QMessageBox.warning(
                    self, "Ошибка",
                    f"Не удалось получить свойства: {e}"
                )

    def format_time(self, epoch_time):
        """
        Форматирование времени из epoch в читаемый формат.
        """
        import datetime
        return datetime.datetime.fromtimestamp(epoch_time).strftime('%Y-%m-%d %H:%M:%S')

    def navigate_to_directory(self, index):
        """
        Обработка выбора директории из дерева папок.
        """
        try:
            folder = self.file_model.filePath(index)
            if os.path.isdir(folder):
                self.current_folder = folder
                self.settings.setValue("last_directory", folder)  # Сохранение последней директории
                self.load_images(folder)
                self.select_first_image()
        except Exception as e:
            QMessageBox.warning(self, "Ошибка", f"Не удалось перейти в директорию: {e}")

    def dragEnterEvent(self, event):
        """
        Обработка события перетаскивания файлов в окно приложения.
        """
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    def dropEvent(self, event):
        """
        Обработка события отпуска файлов после перетаскивания в окно приложения.
        """
        urls = event.mimeData().urls()
        if urls:
            filepath = urls[0].toLocalFile()
            if os.path.isdir(filepath):
                self.current_folder = filepath
                self.settings.setValue("last_directory", filepath)  # Сохранение последней директории
                self.load_images(filepath)
                self.select_first_image()
            elif os.path.isfile(filepath) and filepath.lower().endswith(SUPPORTED_FORMATS):
                folder = os.path.dirname(filepath)
                self.current_folder = folder
                self.settings.setValue("last_directory", folder)  # Сохранение последней директории
                self.load_images(folder)
                self.select_image(filepath)
            else:
                QMessageBox.information(self, "Неверный формат", "Перетащенный файл не поддерживается.")

    def closeEvent(self, event):
        """
        Обработка события закрытия окна приложения.
        """
        try:
            # Сохранение состояний разделителей
            self.save_splitter_proportions()
        except Exception as e:
            print(f"Ошибка сохранения состояний разделителей: {e}")

        self.save_favorites()
        event.accept()

    def open_desktop(self):
        """
        Быстрый доступ к рабочему столу текущего пользователя.
        """
        desktop_path = QStandardPaths.writableLocation(QStandardPaths.DesktopLocation)
        if os.path.exists(desktop_path):
            self.current_folder = desktop_path
            self.settings.setValue("last_directory", desktop_path)  # Сохранение последней директории
            self.load_images(desktop_path)
            self.select_first_image()
            # Также можно установить выбранную папку в дереве, но это требует дополнительных шагов
        else:
            QMessageBox.warning(self, "Ошибка", "Не удалось найти папку Рабочего стола.")

    def save_splitter_proportions(self):
        """
        Сохранение пропорций разделителей (splitters) в QSettings.
        """
        # Сохранение пропорций splitter_main (horizontal)
        sizes_main = self.splitter_main.sizes()
        total_main = sum(sizes_main)
        if total_main > 0:
            proportions_main = [size / total_main for size in sizes_main]
            # Сериализуем список пропорций в JSON строку
            proportions_main_json = json.dumps(proportions_main)
            self.settings.setValue("splitter_main_proportions", proportions_main_json)

        # Сохранение пропорций splitter_images (vertical)
        sizes_images = self.splitter_images.sizes()
        total_images = sum(sizes_images)
        if total_images > 0:
            proportions_images = [size / total_images for size in sizes_images]
            # Сериализуем список пропорций в JSON строку
            proportions_images_json = json.dumps(proportions_images)
            self.settings.setValue("splitter_images_proportions", proportions_images_json)

    def load_splitter_proportions(self):
        """
        Загрузка пропорций разделителей (splitters) из QSettings.
        """
        # Загрузка пропорций splitter_main (horizontal)
        proportions_main_json = self.settings.value("splitter_main_proportions")
        if proportions_main_json and isinstance(proportions_main_json, str):
            try:
                proportions_main = json.loads(proportions_main_json)
                if isinstance(proportions_main, list):
                    # Получаем текущий размер splitter_main
                    splitter_main_total = self.splitter_main.size().width()
                    if splitter_main_total == 0:
                        splitter_main_total = self.width()  # Используем ширину окна
                    # Вычисляем новые размеры на основе сохраненных пропорций
                    new_sizes_main = [int(proportion * splitter_main_total) for proportion in proportions_main]
                    self.splitter_main.setSizes(new_sizes_main)
            except json.JSONDecodeError:
                print("Ошибка декодирования JSON для splitter_main_proportions")

        # Загрузка пропорций splitter_images (vertical)
        proportions_images_json = self.settings.value("splitter_images_proportions")
        if proportions_images_json and isinstance(proportions_images_json, str):
            try:
                proportions_images = json.loads(proportions_images_json)
                if isinstance(proportions_images, list):
                    # Получаем текущий размер splitter_images
                    splitter_images_total = self.splitter_images.size().height()
                    if splitter_images_total == 0:
                        splitter_images_total = self.height()  # Используем высоту окна
                    # Вычисляем новые размеры на основе сохраненных пропорций
                    new_sizes_images = [int(proportion * splitter_images_total) for proportion in proportions_images]
                    self.splitter_images.setSizes(new_sizes_images)
            except json.JSONDecodeError:
                print("Ошибка декодирования JSON для splitter_images_proportions")

    def apply_theme(self):
        """
        Применяет тему приложения в зависимости от текущей темы Windows (светлая или темная).
        """
        if is_windows_dark_mode():
            # Темная тема
            dark_palette = QPalette()
            dark_palette.setColor(QPalette.Window, QColor(53, 53, 53))
            dark_palette.setColor(QPalette.WindowText, Qt.white)
            dark_palette.setColor(QPalette.Base, QColor(25, 25, 25))
            dark_palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            dark_palette.setColor(QPalette.ToolTipBase, Qt.white)
            dark_palette.setColor(QPalette.ToolTipText, Qt.white)
            dark_palette.setColor(QPalette.Text, Qt.white)
            dark_palette.setColor(QPalette.Button, QColor(53, 53, 53))
            dark_palette.setColor(QPalette.ButtonText, Qt.white)
            dark_palette.setColor(QPalette.BrightText, Qt.red)
            dark_palette.setColor(QPalette.Link, QColor(42, 130, 218))
            dark_palette.setColor(QPalette.Highlight, QColor(42, 130, 218))
            dark_palette.setColor(QPalette.HighlightedText, Qt.black)
            self.setPalette(dark_palette)
            self.setStyleSheet("""
                QMainWindow {
                    background-color: #2b2b2b;
                }
                QListWidget {
                    background-color: #2b2b2b;
                    color: white;
                }
                QTreeView {
                    background-color: #2b2b2b;
                    color: white;
                }
                QPushButton {
                    background-color: #3c3c3c;
                    color: white;
                    border: none;
                    padding: 5px 10px;
                }
                QPushButton:hover {
                    background-color: #555555;
                }
            """)
        else:
            # Светлая тема
            light_palette = QApplication.style().standardPalette()
            self.setPalette(light_palette)
            self.setStyleSheet("""
                QMainWindow {
                    background-color: white;
                }
                QListWidget {
                    background-color: white;
                    color: black;
                }
                QTreeView {
                    background-color: white;
                    color: black;
                }
                QPushButton {
                    background-color: #f0f0f0;
                    color: black;
                    border: none;
                    padding: 5px 10px;
                }
                QPushButton:hover {
                    background-color: #d0d0d0;
                }
            """)


if __name__ == "__main__":
    try:
        app = QApplication(sys.argv)
        viewer = ImageViewer()
        viewer.show()
        sys.exit(app.exec_())
    except Exception as e:
        print(f"Не удалось запустить приложение: {e}")
брать из темы весть стиль windows включая ползунки полосы прокрутки , фон в окне просмотра так же поменять на цвет окон из темы windows, исправить и написать обновленный код