"""
Пример 3.1: Вычисляемые свойства без декоратора

Демонстрация использования ComputedProperty без @computed_property:
- Явное объявление вычисляемых свойств
- Автоматическое обновление при изменении зависимостей
- Read-only свойства
- Реактивная архитектура
- Зависимости указываются как list[ObservableProperty]
"""

import sys
from qtpy.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QLabel, QDoubleSpinBox
)
from qtmvvm import BaseViewModel, ComputedProperty


class CalculatorViewModel(BaseViewModel):
    """ViewModel для калькулятора"""
    price: float = 100.0
    quantity: int = 1
    discount: float = 0.0

    def compute_subtotal(self) -> float:
        """Стоимость без скидки"""
        return self.price * self.quantity

    def compute_discount_amount(self) -> float:
        """Сумма скидки"""
        return self.subtotal() * (self.discount / 100)

    def compute_total(self) -> float:
        """Итоговая сумма"""
        return self.subtotal() - self.discount_amount()

    def compute_total_formatted(self) -> str:
        """Форматированная итоговая сумма"""
        return f"{self.total():.2f} ₽"


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Пример 3.1: Вычисляемые свойства без декоратора")

        self.vm = CalculatorViewModel()

        # Создаём вычисляемые свойства явно, без декоратора
        # Зависимости указываются как list[ObservableProperty | ComputedProperty]
        # ComputedProperty сам подключается к сигналам зависимостей
        object.__setattr__(self.vm, 'subtotal', ComputedProperty(
            getter=lambda: self.vm.compute_subtotal(),
            depends_on=[
                self.vm.price,
                self.vm.quantity
            ],
            parent=self.vm
        ))
        object.__setattr__(self.vm, 'discount_amount', ComputedProperty(
            getter=lambda: self.vm.compute_discount_amount(),
            depends_on=[
                self.vm.subtotal,  # Можно указывать ComputedProperty напрямую
                self.vm.discount
            ],
            parent=self.vm
        ))
        object.__setattr__(self.vm, 'total', ComputedProperty(
            getter=lambda: self.vm.compute_total(),
            depends_on=[
                self.vm.subtotal,
                self.vm.discount_amount
            ],
            parent=self.vm
        ))
        object.__setattr__(self.vm, 'total_formatted', ComputedProperty(
            getter=lambda: self.vm.compute_total_formatted(),
            depends_on=[self.vm.total],
            parent=self.vm
        ))

        # Виджеты ввода
        self.price_edit = QDoubleSpinBox()
        self.price_edit.setRange(0, 1000000)
        self.price_edit.setSuffix(" ₽")

        self.quantity_spin = QDoubleSpinBox()
        self.quantity_spin.setRange(1, 1000)

        self.discount_spin = QDoubleSpinBox()
        self.discount_spin.setRange(0, 100)
        self.discount_spin.setSuffix(" %")

        # Виджеты для вычисляемых значений (только чтение)
        self.subtotal_label = QLabel()
        self.discount_label = QLabel()
        self.total_label = QLabel()
        self.total_label.setStyleSheet("font-size: 18px; font-weight: bold;")

        # Привязка входных данных (2-way)
        self.vm.price @ self.price_edit
        self.vm.quantity @ self.quantity_spin
        self.vm.discount @ self.discount_spin

        # Привязка вычисляемых значений (1-way, только чтение)
        self.vm.subtotal >> self.subtotal_label
        self.vm.discount_amount >> self.discount_label
        self.vm.total_formatted >> self.total_label

        # Компоновка
        layout = QVBoxLayout()
        layout.addWidget(QLabel("Цена:"))
        layout.addWidget(self.price_edit)
        layout.addWidget(QLabel("Количество:"))
        layout.addWidget(self.quantity_spin)
        layout.addWidget(QLabel("Скидка:"))
        layout.addWidget(self.discount_spin)

        layout.addWidget(QLabel("<hr>"))
        layout.addWidget(QLabel("Подытог:"))
        layout.addWidget(self.subtotal_label)
        layout.addWidget(QLabel("Скидка:"))
        layout.addWidget(self.discount_label)
        layout.addWidget(QLabel("<hr>"))
        layout.addWidget(QLabel("Итого:"))
        layout.addWidget(self.total_label)

        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
