﻿"""
Zadanie 01: Pełna kontrola błędów (try-except-else-finally)

Zadanie polega na zaimplementowaniu pełnego bloku obsługi wyjątków (try-except-else-finally)
przy operacjach na plikach. Obejmuje to precyzyjne przechwytywanie błędów braku pliku
czy uprawnień oraz zagwarantowanie zamknięcia zasobów w bloku finally.
"""

def read_file_content(file_path: str) -> None:
    """
    Reads the content of a file and prints it, demonstrating the full try-except-else-finally block.
    
    Args:
        file_path (str): The path to the file to open.
    """
    print(f">>> Podaj plik: {file_path}")
    
    try:
        # Próba otwarcia pliku - kod "ryzykowny"
        # Może rzucić FileNotFoundError, PermissionError lub ogólny IOError
        f = open(file_path, 'r', encoding='utf-8')
        
    except FileNotFoundError:
        # Obsługa specyficznego błędu - braku pliku
        print("[ERROR] Nie znaleziono takiego pliku!")
        
    except PermissionError:
        # Obsługa braku uprawnień do pliku
        print("[ERROR] Brak uprawnień do odczytu tego pliku!")
        
    except IOError as e:
        # Ogólna obsługa błędów wejścia/wyjścia (np. uszkodzony system plików)
        print(f"[ERROR] Wystąpił błąd operacji wejścia/wyjścia: {e}")
        
    except Exception as e:
        # Asekuracyjne przechwycenie wszelkich innych, niespodziewanych wyjątków
        print(f"[ERROR] Wystąpił niespodziewany błąd: {e}")
        
    else:
        # Blok 'else' wykonuje się TYLKO wtedy, gdy blok 'try' nie rzucił ŻADNEGO wyjątku.
        # Jest to idealne miejsce na logikę, która zależy od pomyślnego wykonania try.
        # Oddziela to kod operacji sukcesu od samego ryzyka błędu.
        print("[SUCCESS] Plik otwarty.")
        content = f.read()
        # Wyświetlamy treść
        print(f"[INFO] Zawartość: {content.strip()}")
            
    finally:
        # Blok 'finally' wykonuje się ZAWSZE, niezależnie od tego, czy wystąpił błąd,
        # czy kod wykonał się pomyślnie. Nawet w przypadku instrukcji return wewnątrz try/except!
        # Jest to krytyczne miejsce do zwalniania zasobów (zamykania plików, połączeń z bazą danych).
        print("[CLEANUP] Zamykanie strumienia danych.")
        
        # Sprawdzamy, czy zmienna 'f' w ogóle została utworzona (czy open() nie rzuciło błędu)
        # Zgodnie ze wskazówkami wykorzystujemy do tego słownik zmiennych lokalnych locals()
        if 'f' in locals():
            # Sprawdzamy czy plik nie jest już przypadkiem zamknięty
            if not f.closed:
                f.close()
                # print("[CLEANUP] Strumień został bezpiecznie zamknięty.")
        print()

if __name__ == "__main__":
    import os
    
    # Tworzymy plik testowy
    test_filename = "test.txt"
    with open(test_filename, "w", encoding="utf-8") as temp_file:
        temp_file.write("Hello World")
        
    # Test 1: Ścieżka do istniejącego pliku (Sukces)
    read_file_content(test_filename)
    
    # Test 2: Błędna ścieżka (Błąd: plik nie istnieje)
    read_file_content("błąd.txt")
    
    # Sprzątanie po teście
    if os.path.exists(test_filename):
        os.remove(test_filename)
