﻿class Produkt:
    """
    Klasa Produkt implementująca logikę tzw. bogatych porównań (Rich Comparisons).
    Pozwala to na wbudowane porównywanie obiektów oraz użycie metod min, max czy sort.
    """
    def __init__(self, nazwa: str, cena: float):
        self.nazwa = nazwa
        self.cena = cena

    def __eq__(self, other) -> bool:
        """
        Definiuje operator równości (==).
        Uznajemy, że produkty są 'równe' w kontekście sortowania, jeśli mają taką samą cenę.
        """
        if isinstance(other, Produkt):
            return self.cena == other.cena
        return False

    def __lt__(self, other) -> bool:
        """
        Definiuje operator mniejszości (<).
        Dzięki tej jednej metodzie Python jest w stanie posortować obiekty.
        Z definicji, mniejszy jest ten produkt, którego cena jest niższa.
        """
        if isinstance(other, Produkt):
            return self.cena < other.cena
        # Gdy porównujemy z całkowicie innym typem, używamy NotImplemented
        # by Python mógł obsłużyć błąd standardowo (TypeError)
        return NotImplemented

    def __repr__(self) -> str:
        """
        Oficjalna reprezentacja ułatwiająca podejrzenie listy produktów 
        po sortowaniu (gdy wypisujemy listę na ekran).
        """
        return f"Produkt(nazwa='{self.nazwa}', cena={self.cena:.2f})"

if __name__ == "__main__":
    p1 = Produkt("Chleb", 5.0)
    p2 = Produkt("Masło", 8.5)
    p3 = Produkt("Mleko", 4.2)
    p4 = Produkt("Bułka", 1.5)
    p5 = Produkt("Bochenek", 5.0) # Cena taka sama jak za chleb

    print("--- Operatory porównania ---")
    print(f"{p1.nazwa} < {p2.nazwa}:", p1 < p2)  # Oczekiwane True
    print(f"{p2.nazwa} > {p3.nazwa}:", p2 > p3)  # Oczekiwane True (automatycznie obsługiwane przez Pythona przez odwrócenie argumentów)
    print(f"{p1.nazwa} == {p5.nazwa}:", p1 == p5) # Oczekiwane True, ze względu na zaimplementowaną metodę __eq__

    print("\n--- Przed sortowaniem ---")
    lista_produktow = [p1, p2, p3, p4, p5]
    for p in lista_produktow:
        print(p)

    print("\n--- Po sortowaniu (z wbudowanym Timsort) ---")
    # Metoda .sort() używa przeciążonego operatora __lt__
    lista_produktow.sort()
    for p in lista_produktow:
        print(p)

    print("\n--- Użycie wbudowanych funkcji min() i max() ---")
    # Działają bezproblemowo na podobnej zasadzie co sortowanie
    print("Najtańszy:", min(lista_produktow))
    print("Najdroższy:", max(lista_produktow))
